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

  • 相关阅读:
    JavaEE 第四周
    JavaEE 第三周
    JavaEE 第二周
    JavaEE 第一周
    js字符串方法
    javaee项目库存管理系统总结
    javaee期末团队项目库存管理系统概要信息
    JAVAEE第十一周
    JSON
    Facelets
  • 原文地址:https://www.cnblogs.com/00isok/p/10485832.html
Copyright © 2011-2022 走看看