zoukankan      html  css  js  c++  java
  • loj136 (最小瓶颈路,多次询问)

    题目描述

    给定一个包含 n nn 个节点和 m mm 条边的图,每条边有一个权值。
    你的任务是回答 k kk 个询问,每个询问包含两个正整数 s ss 和 t tt 表示起点和终点,要求寻找从 s ss 到 t tt 的一条路径,使得路径上权值最大的一条边权值最小。

    输入格式

    第一行包含三个整数 n nn、m mm、k kk,分别表示 n nn 个节点, m mm 条路径, k kk 个询问。

    接下来 m mm 行,每行三个整数 u uu , v vv , w ww, 表示一个由 u uu 到 v vv 的长度为 w ww 的双向边。

    再接下来 k kk 行,每行两个整数 s ss , t tt,表示询问从 s ss 连接到 t tt 的所有路径中单边长度最大值的最小值。

    输出格式

    输出包含 k kk 行,每一行包含一个整数 p pp 。p pp 表示 s ss 连接到 t tt 的所有路径中单边长度最大值的最小值。另外,如果 s ss 到 t tt 没有路径相连通,输出 -1 即可。

    样例

    样例输入

    8 11 3
    1 2 10
    2 5 50
    3 4 60
    7 5 60
    3 6 30
    1 5 30
    6 7 20
    1 7 70
    2 3 20
    3 5 40
    2 6 90
    1 7
    2 8
    6 2

    样例输出

    30
    -1
    30

    数据范围与提示

    对于 30% 30\%30% 的数据 n≤100,m≤1000,k≤100,w≤1000 n leq 100, m leq 1000, k leq 100, w leq 1000n100,m1000,k100,w100
    对于 70% 70\%70% 的数据 n≤1000,m≤10000,k≤1000,w≤100000 n leq 1000, m leq 10000, k leq 1000, w leq 100000n1000,m10000,k1000,w10000
    对于 100% 100\%100% 的数据 n≤1000,m≤100000,k≤1000,w≤10000000 n leq 1000, m leq 100000, k leq 1000, w leq 10000000n1000,m100000,k1000,w1000000
    本题可能会有重边。
    为了避免 Special Judge,本题所有的 w ww 均不相同。

    题解:

    同样是基于最小生成树,我们将其中关键信息保存

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN=1000+10;
    const int INF=0x3f3f3f3f;
    int n,m,k;
    int mapp[MAXN][MAXN];
    int ans[MAXN][MAXN],dis[MAXN],pri[MAXN];
    bool vis[MAXN];
    void prim()
    {
        memset(vis, false, sizeof(vis));
        for (int i = 1; i <=n ; ++i)
        {
            dis[i]=INF;
            pri[i]=i;
        }
        dis[1]=0;
        for (int i = 1; i <=n ; ++i) {
            int MAXX=INF,v=-1;
            for (int j = 1; j <=n ; ++j) {
                if(!vis[j]&&dis[j]<MAXX)
                {
                    MAXX=dis[v=j];
                }
            }
            if(v==-1)
                break;
            for (int j = 1; j <=n ; ++j) {
                if(vis[j])
                {
                    ans[v][j]=ans[j][v]=max(ans[pri[v]][j],MAXX);
                }
            }
            vis[v]=true;
            for (int j = 1; j <=n ; ++j) {
                if(!vis[j]&&mapp[v][j]<dis[j])
                {
                    dis[j]=mapp[v][j];
                    pri[j]=v;
                }
            }
        }
    }
    
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        int x,y,z;
        memset(mapp,0x3f, sizeof(mapp));
        memset(ans,0, sizeof(ans));
        for (int i = 0; i <=n ; ++i) {
            mapp[i][i]=0;
        }
        for (int i = 0; i <m ; ++i) {
            scanf("%d%d%d",&x,&y,&z);
            if(mapp[x][y]>z)
                mapp[x][y]=mapp[y][x]=z;
        }
        prim();
        while(k--)
        {
            scanf("%d%d",&x,&y);
    
            printf("%d
    ",ans[x][y]==0?-1:ans[x][y]);
        }
        return 0;
    }
    
    
    //int prim(int s)
    //{
    //    int res=0;
    //    memset(ans,0,sizeof(ans));// 初始化目标数组
    //    for(int i=1;i<=n;i++)
    //        vis[i] = false, d[i] = INF, pri[i]=i;//初始化 标记、距离、父亲数组。
    //
    //    d[s]=0; // 自身的距离为零
    //    for(int i=0;i<n;i++) // prim考察剩下的n - 1个点
    //    {
    //        int maxx=INF, v=-1; // 比较和点的位置
    //        for(int j=1;j<=n;j++) // 寻找与最小生成树集合最近的点
    //        {
    //            if(!vis[j]&&d[j]<maxx)
    //            {
    //                maxx=d[v=j]; // 写法不错
    //            }
    //        }
    //        if(v==-1) // 未找到的判断
    //            break;
    //
    //        for(int j=1;j<=n;j++) //
    //            if(vis[j])
    //                ans[v][j] = ans[j][v] = max(ans[pri[v]][j], maxx);
    //
    //        res+=maxx; // 最小生成树权值更新
    //        vis[v]=true; // 将找到的点加入集合
    //
    //        for(int j=1;j<=n;j++)
    //        {
    //            if(!vis[j]&&mapp[v][j]<d[j])
    //            {
    //                d[j] = mapp[v][j]; // 更新距离
    //                pri[j] = v; // 更新父亲节点。
    //            }
    //        }
    //    }
    //    return res;
    //}
    

      

  • 相关阅读:
    linux驱动---等待队列、工作队列、Tasklets【转】
    Pinctrl子系统之一了解基础概念【转】
    Linux内存管理(最透彻的一篇)【转】
    linux驱动学习笔记---实现中断下半部以及驱动编写规范(七)【转】
    一些网址下载【转】
    Linux /proc/$pid部分内容详解【转】
    Linux kernel workqueue机制分析【转】
    Linux进程核心调度器之主调度器schedule--Linux进程的管理与调度(十九)【转】
    Linux Kernel PANIC(三)--Soft Panic/Oops调试及实例分析【转】
    Linux内核调试的方式以及工具集锦【转】
  • 原文地址:https://www.cnblogs.com/-xiangyang/p/9803709.html
Copyright © 2011-2022 走看看