zoukankan      html  css  js  c++  java
  • POJ 3662 Telephone Lines【二分答案+最短路】||【双端队列BFS】

    <题目链接>

    题目大意:

    在一个节点标号为1~n的无向图中,求出一条1~n的路径,使得路径上的第K+1条边的边权最小。

    解题分析:
    直接考虑情况比较多,所以我们采用二分答案,先二分枚举第K+1条路的边权,然后根据枚举的边权,重新建图。因为john只需要支付除K条边之后权值最大的边,所以对于所有边权小于等于枚举边的,将其边权置为0,对于那些大于枚举边权的边,边权则置为1,这样,对1~n跑最短路,就能够用于判断枚举的答案是否成立。因为建的是边权为0、1的图求最短路,所以也可以用双端队列实现的BFS求解。

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <algorithm>
    using namespace std;
    
    #define clr(a,b) memset(a,b,sizeof(a))
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define pb push_back
    const int N = 1e3+5, M = 1e4+5;
    const int INF = 0x3f3f3f3f;
    int n,m,k,cnt,head[N],vis[N];
    struct Edge{
        int to,nxt,val;
    }edge[M<<1];
    
    struct Ege{    //记录下初始输入边的个数
        int x,y,w;
        Ege(int _x=0,int _y=0,int _w=0):x(_x),y(_y),w(_w){}
    };
    vector<Ege>vec;
    
    struct Node{
        int dist,loc;
        Node(int _dist=0,int _loc=0):dist(_dist),loc(_loc){}
        bool operator <(const Node &tmp)const{ return dist>tmp.dist; }
    }node[N];
    
    void init(){
        cnt=0;clr(head,-1);
    }
    void addedge(int u,int v,int w){
        edge[++cnt].to=v,edge[cnt].val=w;
        edge[cnt].nxt=head[u],head[u]=cnt;
    }
    void Getmap(int x){     
        init();
        for(int i=0;i<vec.size();i++){
            Ege now=vec[i];
            int u=now.x,v=now.y,w=now.w;    
            if(w<=x)addedge(u,v,0),addedge(v,u,0);    //将花费<=k的道路边权置0,因为john只需要支付最大的道路
            else addedge(u,v,1),addedge(v,u,1);    //大于的边置为1,免费的k条边是否能够在满足题目条件的情况下,连通1~n点
        }
    }
    bool check(int x){
        Getmap(x);    //根据枚举的答案,建立0、1图,然后在这个0、1图上跑最短路
        priority_queue<Node>q;
        for(int i=1;i<=n;i++){
            vis[i]=0,node[i].loc=i,node[i].dist=INF;
        }
        node[1].dist=0;
        q.push(node[1]);
        while(q.size()){
            int u=q.top().loc;q.pop();
            if(vis[u])continue;
            vis[u]=1;
            for(int i=head[u];~i;i=edge[i].nxt){
                int v=edge[i].to;
                if(node[v].dist>node[u].dist+edge[i].val){
                    node[v].dist=node[u].dist+edge[i].val;
                    q.push(node[v]);
                }
            }
        }
        if(node[n].dist<=k)return true;
        return false; 
    }
    int main(){
        while(scanf("%d%d%d",&n,&m,&k)!=EOF){
            rep(i,1,m){
                int u,v,w;scanf("%d%d%d",&u,&v,&w);
                vec.pb(Ege(u,v,w));
            }
            int l=0,r=1e6+10,ans=-1;
            while(l<=r){    //二分答案,枚举john需要支付的钱数,即连通1~n的道路中,除k条路外,花费最大的路径
                int mid=l+r>>1;
                if(check(mid))ans=mid,r=mid-1;
                else l=mid+1;
            }
            printf("%d
    ",ans);
        }
    }

    2019-03-06

  • 相关阅读:
    安全编码1
    VPP tips
    VPP概述汇总
    C语言安全编码摘录
    TCP-proxy
    Scipy Lecture Notes学习笔记(一)Getting started with Python for science 1.4. Matplotlib: plotting
    Scipy Lecture Notes学习笔记(一)Getting started with Python for science 1.3. NumPy: creating and manipulating numerical data
    Scipy Lecture Notes学习笔记(一)Getting started with Python for science 1.2. The Python language
    Scipy Lecture Notes学习笔记(一)Getting started with Python for science 1.1. Python scientific computing ecosystem
    25马5跑道,求最快的五匹马的需要比赛的次数
  • 原文地址:https://www.cnblogs.com/00isok/p/10485832.html
Copyright © 2011-2022 走看看