先求出整个图的最大生成树,然后做树上LCA.
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 5 using namespace std; 6 7 int n,m,tot,head[10001],fa[10001],_tot,d[10001]; 8 int p[10001][21],q,fv[10001][21],ans = 0x7f7f7f7f; 9 bool vis[10001]; 10 struct kkk{ 11 int vi,to,from; 12 }e[100002]; 13 struct k2 { 14 int next,v,to; 15 }e1[100002]; 16 17 inline int find_father(int x) { 18 if(fa[x] == x) return fa[x]; 19 return fa[x] = find_father(fa[x]); 20 } 21 22 inline void add(int x,int y,int z) { 23 e[++tot].to = y; 24 e[tot].vi = z; 25 e[tot].from = x; 26 } 27 28 inline bool cmp(kkk a,kkk b) { 29 return a.vi > b.vi; 30 } 31 32 inline void add2(int x,int y,int z) { 33 e1[++_tot].to = y; 34 e1[_tot].next = head[x]; 35 e1[_tot].v = z; 36 head[x] = _tot; 37 } 38 39 inline void kruskal() { 40 for(int i = 1;i <= n; i++) 41 fa[i] = i; 42 sort(e+1,e+1+m+m,cmp);//因为是双向边,所以要加2*m,卡了好久,感谢Candy?大佬 43 for(int i = 1;i <= m + m; i++) { 44 int t = e[i].to; 45 int f = e[i].from; 46 int tt = find_father(t); 47 int ff = find_father(f); 48 if(tt != ff) { 49 add2(t,f,e[i].vi); 50 add2(f,t,e[i].vi); 51 fa[tt] = ff; 52 } 53 } 54 } 55 56 inline void dfs(int u) { 57 vis[u] = 1; 58 for(int i = 1;(1 << i) <= d[u]; i++){ 59 p[u][i] = p[p[u][i-1]][i-1]; 60 fv[u][i] = min(fv[u][i-1],fv[p[u][i-1]][i-1]); 61 } 62 for(int i = head[u];i != 0; i = e1[i].next) { 63 int oo = e1[i].to; 64 if(!vis[oo]) { 65 d[oo] = d[u] + 1; 66 fv[oo][0] = e1[i].v;//记录自己到父亲的边的值 67 p[oo][0] = u;//记录自己的父亲 68 dfs(oo); 69 } 70 } 71 } 72 73 inline int lca(int x,int y) { 74 ans = 0x7f7f7f7f; 75 if(find_father(x) != find_father(y)) return -1; 76 if(d[x] > d[y]) 77 swap(x,y); 78 for(int i = 20;i >= 0; i--) 79 if(d[x] <= d[p[y][i]]) { 80 ans = min(ans,fv[y][i]); 81 y = p[y][i]; 82 } 83 if(x == y) return ans; 84 for(int i = 20;i >= 0; i--) { 85 if(p[x][i] != p[y][i]) { 86 ans = min(ans,min(fv[x][i],fv[y][i])); 87 x = p[x][i]; 88 y = p[y][i]; 89 } 90 } 91 ans = min(ans,min(fv[x][0],fv[y][0])); 92 return ans; 93 } 94 95 int main() { 96 scanf("%d%d",&n,&m); 97 for(int i = 1;i <= m; i++) { 98 int x,y,z; 99 scanf("%d%d%d",&x,&y,&z); 100 add(x,y,z); 101 add(y,x,z); 102 } 103 kruskal(); 104 for(int i = 1;i <= n; i++) 105 if(!vis[i]) { 106 d[i] = 1; 107 dfs(i); 108 p[i][0] = i; 109 fv[i][0] = 0x7f7f7f7f; 110 } 111 scanf("%d",&q); 112 for(int i = 1;i <= q; i++) { 113 int x,y; 114 scanf("%d%d",&x,&y); 115 printf("%d\n",lca(x,y)); 116 } 117 return 0; 118 }
原文:https://www.cnblogs.com/lipeiyi520/p/11968010.html