LOJ 架设电话线 【二分 + spfa】

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 }
View Code

fighting fighting fighting

猜你喜欢

转载自www.cnblogs.com/Frank-King/p/9751472.html