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; }