【Luogu】P1948电话线(二分SPFA)
二分最长的电话线长度。把所有大于这个长度的边权设成1,小于等于的设成零,然后跑SPFA看dis[n]是否>k。若>k则l=mid+1
否则r=mid-1
放代码
#include<cstdio> #include<cctype> #include<cstring> #include<algorithm> inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } struct Edge{ int next,to,dis; }edge[1000010]; int head[100100],num; inline void add(int from,int to,int dis){ edge[++num]=(Edge){head[from],to,dis}; head[from]=num; } int val[100010]; int f[1000001],h,t=1; bool vis[100010]; int dis[100010]; int ans; int main(){ int n=read(),m=read(),k=read(); for(int i=1;i<=m;++i){ int from=read(),to=read(),dst=read(); add(from,to,dst); add(to,from,dst); val[i]=dst; } std::sort(val+1,val+m+1); int l=1,r=m; while(l<=r){ int mid=(l+r)>>1; int cost=val[mid]; memset(vis,0,sizeof(vis)); memset(dis,127/3,sizeof(dis)); f[1]=1;h=0;t=1;dis[1]=0; while(h++<t){ int from=f[h]; vis[from]=0; for(int i=head[from];i;i=edge[i].next){ int to=edge[i].to; int c; if(edge[i].dis<=cost) c=0; else c=1; if(dis[to]>dis[from]+c){ dis[to]=dis[from]+c; if(!vis[to]){ vis[to]=1; f[++t]=to; } } } } if(dis[n]>k) l=mid+1; else{ ans=cost; r=mid-1; } } printf("%d",ans==0?-1:ans); return 0; }