LOJ 架设电话线
题面见链接。。。
题解:
一般来说看到这总 第 k 大的 都往二分想想。
这题其实蛮基础的。
二分这第 k +1 大的边的权值,然后整个图的边比它大的权值为 1 ,比他小的权值为 0 。 最后跑一遍 spfa 求出整个图的最短路径,如果 <= K 则成立,可继续缩小范围,否则则只能增加范围。。。
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=4005; 4 int n,p,k,x,y,z,nxt[N],to[N],hea[N],w[N],cnt=0; 5 bool vis[N]; 6 int dis[N],q[N],h,t,ans; 7 inline void add(int x,int y,int ww) 8 { 9 to[++cnt]=y; nxt[cnt]=hea[x]; hea[x]=cnt; w[cnt]=ww; 10 } 11 inline bool check(int mx) 12 { 13 memset(vis,0,sizeof(vis)); 14 memset(dis,60,sizeof(dis)); dis[1]=0; vis[1]=true; 15 h=0,t=1; q[1]=1; 16 while (h<t) 17 { 18 int x=q[++h]; vis[x]=false; 19 for (int i=hea[x]; i; i=nxt[i]) 20 { 21 int u=to[i]; 22 if (dis[u]>dis[x]+(w[i]>mx)) 23 { 24 dis[u]=dis[x]+(w[i]>mx); 25 if (vis[u]) continue; 26 vis[u]=true; q[++t]=u; 27 } 28 } 29 } 30 if (dis[n]<=k) return true; else return false; 31 } 32 int main() 33 { 34 scanf("%d%d%d",&n,&p,&k); 35 for (int i=1; i<=p; ++i) 36 { 37 scanf("%d%d%d",&x,&y,&z); 38 add(x,y,z); add(y,x,z); 39 } 40 int l=0,r=1000000; ans=0x3f3f3f3f; 41 while (l<=r) 42 { 43 int mid=(l+r)/2; 44 if (check(mid)) ans=min(ans,mid),r=mid-1; 45 else l=mid+1; 46 } 47 if (ans==0x3f3f3f3f) printf("-1\n"); else printf("%d\n",ans); 48 return 0; 49 }
fighting fighting fighting