zoukankan      html  css  js  c++  java
  • 洛谷P1948Telephone Lines && poj3662 (二分+最短路)

    题目链接:洛谷P1948[USACO08JAN]电话线Telephone Lines

    分析:

    题意:在无向图中找到一条路径,可以使k条边花费0,最后花费即为剩下的边中最大值,使这个最大值最小。

    1.使最大值最小的问题明显可以二分一个mid。

    2.由贪心可知,使k条花费为0必然是最大的k条边,即要求的值是路径中第k+1大的路径长度。

    那么我们现在二分了一个值了,怎么check路径上是否有<=k条边小于mid呢?当然是规避比mid大的边走啦。

    通过把>mid的边设成1,<=mid的边设成0,跑最短路

    //洛谷P1948 
    #include<bits/stdc++.h>
    using namespace std;
    #define N 1005
    #define M 20005
    int head[N],val[M],nex[M],to[M],w[M],dis[N],vis[N];
    int tot=0,n,k;
    void add(int a,int b,int ww){ to[++tot]=b; nex[tot]=head[a]; head[a]=tot; val[tot]=ww; }
    struct pack{
        int s,dis;
    };
    priority_queue<pack> q;
    bool operator < (const pack &a,const pack &b){
        return a.dis>b.dis;
    }
    int dij()
    {
        memset(dis,0x7f7f7f,sizeof(dis));
        memset(vis,0,sizeof(vis));
        int s=1,t=n;
        dis[s]=0; q.push((pack){s,dis[s]});
        while(!q.empty()){
            pack t=q.top(); q.pop();
            int u=t.s;
            if(vis[u]) continue;
            vis[u]=1;
            for(int i=head[u];i;i=nex[i]){
                int v=to[i];
                if(dis[v]>dis[u]+w[i]){
                    dis[v]=dis[u]+w[i];
                    if(!vis[v]) q.push((pack){v,dis[v]});
                } 
            }
        }
        return dis[t];
    }
    bool check(int x)
    {
        memset(w,0,sizeof(w));
        for(int i=1;i<=tot;i++) if(val[i]>x) w[i]=1;
        int diss=dij();
        if(diss<=k) return true;
        if(diss==2139062143) { printf("-1"); exit(0); }
        return false;
    }
    int main()
    {
        int m,a,b,c,maxn=0,ans=0;
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c); add(b,a,c);
            maxn=max(maxn,c);
        }
        int l=0,r=maxn;
        while(l<r){
            int mid=(l+r)>>1;
            if(!check(mid)) l=mid+1;
            else r=mid,ans=mid;
        }
        printf("%d
    ",ans);
        return 0;
    }
    /*
    6 7 2
    1 2 5
    3 1 4
    2 4 8
    3 2 3
    5 2 9
    3 4 7
    4 5 6
    */
  • 相关阅读:
    java语言基础
    常用4种限流算法介绍及比较
    如何用Redis实现分布式锁
    翻转字符串
    JAVA之io流
    JAVA之Collections集合
    【转】IT行业岗位以及发展方向
    JAVA之字符串
    JAVA之数组
    Linux之判断字符串是否为空
  • 原文地址:https://www.cnblogs.com/mowanying/p/11386657.html
Copyright © 2011-2022 走看看