luogu P1967 货车运输 最大生成树 倍增LCA
Posted iat14
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P1967 货车运输 最大生成树 倍增LCA相关的知识,希望对你有一定的参考价值。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 struct edg 7 { 8 int x,y,w; 9 friend bool operator < (edg x,edg y) 10 { 11 return x.w > y.w; 12 } 13 } vec[110000]; 14 const int inf = 999999999; 15 int n,m,q,cnt,l; 16 int head[20010],nxt[150000],to[150000],val[150000]; 17 int p[20010][32],fa[100000],size[100000]; 18 int minn[20010][32],deep[20010]; 19 bool vis[20010]; 20 void add(int x,int y,int w) 21 { 22 cnt++; 23 nxt[cnt] = head[x]; 24 head[x] = cnt; 25 to[cnt] = y; 26 val[cnt] = w; 27 } 28 int getfa(int x) 29 { 30 if (fa[x] == x) 31 return x; 32 return fa[x] = getfa(fa[x]); 33 } 34 void merge(int x,int y) 35 { 36 int s1 = getfa(x),s2 = getfa(y); 37 if (s1 == s2) 38 return; 39 if (size[s1] < size[s2]) 40 { 41 fa[s1] = s2; 42 size[s2] += size[s1]; 43 }else 44 { 45 fa[s2] = s1; 46 size[s1] += size[s2]; 47 } 48 } 49 void dfs(int x) 50 { 51 vis[x] = true; 52 for (int tp = head[x];tp;tp = nxt[tp]) 53 { 54 if (vis[to[tp]]) 55 continue; 56 deep[to[tp]] = deep[x] + 1; 57 p[to[tp]][0] = x; 58 minn[to[tp]][0] = val[tp]; 59 dfs(to[tp]); 60 } 61 } 62 void init() 63 { 64 for (int i = 1;i <= n;i++) 65 if (!vis[i]) 66 { 67 p[i][0] = 0; 68 deep[i] = 1; 69 dfs(i); 70 } 71 l = log2(n); 72 for (int i = 1;i <= l;i++) 73 for (int j = 1;j <= n;j++) 74 { 75 p[j][i] = p[p[j][i - 1]][i - 1]; 76 minn[j][i] = min(minn[j][i - 1],minn[p[j][i - 1]][i - 1]); 77 } 78 } 79 int lca(int a,int b) 80 { 81 int ans = inf; 82 if (deep[a] < deep[b]) 83 swap(a,b); 84 for (int j = l;j >= 0;j--) 85 if (deep[p[a][j]] >= deep[b]) 86 { 87 ans = min(ans,minn[a][j]); 88 a = p[a][j]; 89 90 } 91 if (a == b) 92 return ans; 93 for (int j = l;j >= 0;j--) 94 { 95 if (p[a][j] != p[b][j]) 96 { 97 ans = min(ans, min(minn[a][j], minn[b][j])); 98 a = p[a][j]; 99 b = p[b][j]; 100 } 101 } 102 if (p[a][0] != p[b][0] || p[a][0] == 0) 103 return -1; 104 ans = min(ans,min(minn[a][0],minn[b][0])); 105 return ans; 106 } 107 int main() 108 { 109 scanf("%d%d",&n,&m); 110 for (int i = 1;i <= m;i++) 111 scanf("%d%d%d",&vec[i].x,&vec[i].y,&vec[i].w); 112 for (int i = 1;i <= n;i++) 113 { 114 fa[i] = i; 115 size[i] = 1; 116 } 117 sort(vec + 1,vec + m + 1); 118 for (int i = 1;i <= m;i++) 119 if (getfa(vec[i].x) != getfa(vec[i].y)) 120 { 121 add(vec[i].x,vec[i].y,vec[i].w); 122 add(vec[i].y,vec[i].x,vec[i].w); 123 merge(vec[i].x,vec[i].y); 124 } 125 init(); 126 scanf("%d",&q); 127 int ta,tb; 128 for (int i = 1;i <= q;i++) 129 { 130 scanf("%d%d",&ta,&tb); 131 printf("%d ",lca(ta,tb)); 132 } 133 return 0; 134 }
以上是关于luogu P1967 货车运输 最大生成树 倍增LCA的主要内容,如果未能解决你的问题,请参考以下文章
luogu1967noip2013 货车运输 [生成树kruskal LCA ]