AcWing 340. 通信线路

原题链接

考察:最短路(双端队列)+二分

想到了二分,结果我是用dfs+二分,跑了6个数据TLE.

思路:

        由题可知,题目是要求最大的第k+1条路径.我们除去k条路径后,就是求剩下的最大值最小.这很容易想到二分.关键是check函数怎么写.本蒟蒻的思路是dfs(当前点,二分值,k). 如果当前路径>二分值,k-1.否则不变.这样可以算出解.但是会TLE.dfs相当于朴素的dijkstra,把每个边和点都算了一边.这里的边有的性质,如果它的权值>二分值,那么k--.如果没有k就不变.我们把k--替换为将此路径的权值改为1,k不变就是改为0.这样就变成了1->n的路径中.是否存在权值和<=k的路径.这样就变成了最短路问题.

        时间复杂度O(P*log2L)

 1 #include <iostream>
 2 #include <cstring>
 3 #include <queue>
 4 using namespace std;
 5 const int N = 1010,M=20010;
 6 int h[N],idx,n,m,k,dist[N];
 7 bool st[N];
 8 struct Road{
 9     int to,ne,w;
10 }road[M<<1];
11 void add(int a,int b,int w)
12 {
13     road[idx].to = b,road[idx].w = w,road[idx].ne = h[a],h[a] = idx++;
14 }
15 bool spfa(int s,int mid)
16 {
17     memset(st,0,sizeof st);
18     memset(dist,0x3f,sizeof dist);
19     queue<int> q;
20     dist[s] = 0;
21     q.push(s);
22     st[s] = 1;
23     while(q.size())
24     {
25         int u = q.front();
26         q.pop();
27         st[u] = 0;
28         for(int i=h[u];~i;i=road[i].ne)
29         {
30             int v = road[i].to,w = 0;
31             if(road[i].w>mid) w = 1;
32             if(dist[v]>dist[u]+w)
33             {
34                 dist[v] = dist[u]+w;
35                 if(!st[v]) q.push(v),st[v] = 1;
36             }
37         }
38     }
39     return dist[n]<=k;
40 }
41 int main()
42 {
43     scanf("%d%d%d",&n,&m,&k);
44     memset(h,-1,sizeof h);
45     int r = 0,l = 0;
46     for(int i=1;i<=m;i++)
47     {
48         int a,b,w; scanf("%d%d%d",&a,&b,&w);
49         add(a,b,w); add(b,a,w);
50         r = max(r,w);
51     }
52     int maxn = r+10;
53     r+=10;
54     while(l<r)
55     {
56         int mid = l+r>>1;
57         if(spfa(1,mid)) r = mid;
58         else l = mid+1;
59     }
60     if(r==maxn) r = -1;
61     printf("%d\n",r);
62     return 0;
63 }

 

posted @ 2021-04-27 19:57  acmloser  阅读(38)  评论(0编辑  收藏  举报