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 }