P1967 [NOIP2013 提高组] 货车运输
Posted acmloser
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1967 [NOIP2013 提高组] 货车运输相关的知识,希望对你有一定的参考价值。
考察:LCA+最大生成树
思路:
实际是求两点之间最大的最短边.这样很容易想到二分,但是直接二分会TLE.
然后又会想到次小生成树,但是这道题边不能构成树.由于我们要的边尽量大,可以考虑贪心一波建立最大生成树.然后求两点之间的最小距离直接套LCA倍增板子.这题比次小生成树省事.
时间复杂度O(mlog2n+q*log2n)
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 using namespace std; 6 const int N = 10010,M = 50010,INF = 0x3f3f3f3f; 7 int n,m,idx,Q,p[N],h[N],depth[N],fa[N][16],d[N][16]; 8 struct Road{ 9 int fr,to,ne,w; 10 }road[M<<1]; 11 struct Path{ 12 int u,v,w; 13 bool operator<(const Path& p)const{ 14 return this->w>p.w; 15 } 16 }path[M]; 17 void add(int a,int b,int w) 18 { 19 road[idx].w =w,road[idx].fr = a,road[idx].to = b,road[idx].ne = h[a],h[a] = idx++; 20 } 21 int findf(int x) 22 { 23 if(p[x]!=x) p[x] = findf(p[x]); 24 return p[x]; 25 } 26 void bfs(int s) 27 { 28 queue<int> q; 29 memset(depth,0x3f,sizeof depth); 30 depth[s] = 1,depth[0] = 0; 31 q.push(s); 32 while(q.size()) 33 { 34 int u = q.front(); 35 q.pop(); 36 for(int i=h[u];~i;i=road[i].ne) 37 { 38 int v = road[i].to; 39 if(depth[v]>depth[u]+1) 40 { 41 depth[v] = depth[u]+1; 42 q.push(v); 43 fa[v][0] = u; d[v][0] = road[i].w; 44 for(int j=1;j<15;j++) 45 { 46 int anc = fa[v][j-1]; 47 fa[v][j] = fa[anc][j-1]; 48 d[v][j] = min(d[anc][j-1],d[v][j-1]); 49 } 50 } 51 } 52 } 53 } 54 int lca(int a,int b) 55 { 56 int ans = INF; 57 if(depth[a]<depth[b]) swap(a,b); 58 for(int i=14;i>=0;i--) 59 if(depth[fa[a][i]]>=depth[b]) 60 { 61 ans = min(d[a][i],ans); 62 a = fa[a][i]; 63 } 64 if(a!=b) 65 { 66 for(int i=14;i>=0;i--) 67 if(fa[a][i]!=fa[b][i]) 68 { 69 ans = min(ans,d[a][i]); 70 ans = min(ans,d[b][i]); 71 a = fa[a][i]; 72 b = fa[b][i]; 73 } 74 ans = min(ans,d[a][0]); 75 ans = min(ans,d[b][0]); 76 } 77 return ans; 78 } 79 void build() 80 { 81 sort(path+1,path+m+1); 82 for(int i=1;i<=m;i++) 83 { 84 int pa = findf(path[i].u),pb = findf(path[i].v),w = path[i].w; 85 if(pa==pb) continue; 86 p[pa] = pb; 87 add(path[i].u,path[i].v,path[i].w); 88 add(path[i].v,path[i].u,path[i].w); 89 } 90 } 91 int main() 92 { 93 scanf("%d%d",&n,&m); 94 for(int i=1;i<=n;i++) h[i] = -1,p[i] = i; 95 for(int i=1;i<=m;i++) 96 { 97 int a,b,w; scanf("%d%d%d",&a,&b,&w); 98 path[i] = {a,b,w}; 99 } 100 build(); 101 bfs(1); 102 scanf("%d",&Q); 103 while(Q--) 104 { 105 int a,b; scanf("%d%d",&a,&b); 106 if(findf(a)!=findf(b)) printf("-1\\n"); 107 else printf("%d\\n",lca(a,b)); 108 } 109 return 0; 110 }
以上是关于P1967 [NOIP2013 提高组] 货车运输的主要内容,如果未能解决你的问题,请参考以下文章
洛谷P1967 [NOIP2013提高组Day1T2]货车运输
[luogu P1967][NOIp2013]P1967 货车运输