Telephone Lines(转换图思维+二分)

题:https://ac.nowcoder.com/acm/problem/24950

题意:给n点,m边无向图,dis[u,v]代表从u到v的路径上边的最大值,现在给定整数k,代表可以抵消掉k条边,问dis[1,n]的最小值。
分析:
    n<=1000,不能直接地对原图进行最短路,我们可以考虑二分考虑答案midd;
    那么我们把图上边大于midd的边设为权值为1,其余为0;
    那么走这个图的最短路,就是找最少数量的边大于midd,midd越小最少数量最多,也满足二分的单调性。

#include<bits/stdc++.h>
using namespace std;
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
#define pb push_back
#define MP make_pair

typedef long long ll;
const int M=2e3+5;
const ll INF=1e18;
vector< pair<int,int> >g[M];
int dis[M],vis[M];
int n,m,k;
queue<int>que;
bool check(int midd){
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[1]=0;
    while(!que.empty())
        que.pop();
    que.push(1);
    vis[1]=1;
    while(!que.empty()){
        int u=que.front();
        que.pop();
        vis[u]=0;
        for(auto it:g[u]){
            int v=it.first,w=it.second;

            int ad=0;
            if(w>midd)
                ad=1;
            if(dis[v]>dis[u]+ad){
                dis[v]=dis[u]+ad;
                if(!vis[v]){
                    vis[v]=1;
                    que.push(v);
                }
            }
        }
    }
    return dis[n]<=k;
}
int main(){
    scanf("%d%d%d",&n,&m,&k);
    for(int u,v,w,i=1;i<=m;i++){
        scanf("%d%d%d",&u,&v,&w);
        g[u].pb(MP(v,w));
        g[v].pb(MP(u,w));
    }
    int l=0,r=1e6,ans=-1;
    while(l<=r){
        int midd=(l+r)>>1;
        if(check(midd)){
            ans=midd;
            r=midd-1;
        }
        else
            l=midd+1;
    }
    printf("%d\n",ans);
    return 0;
}
View Code

 

posted @ 2020-09-13 17:03  starve_to_death  阅读(168)  评论(0编辑  收藏  举报