倍增法求LCA
可以利用LCA快速的求出树上两点间的最短路
时间复杂度O(nlogn)
1 #include<iostream> 2 #include<string.h> 3 #include<algorithm> 4 #include<vector> 5 #include<map> 6 #include<bitset> 7 #include<set> 8 #include<math.h> 9 #include<string> 10 #if !defined(_WIN32) 11 #include<bits/stdc++.h> 12 #endif // !defined(_WIN32) 13 #define ll long long 14 #define dd double 15 using namespace std; 16 struct edge 17 { 18 int to; 19 int weight; 20 int next; 21 }e[500005]; 22 int head[100086]; 23 int p[100086][25]; 24 int deep[100086]; 25 ll dis[100086]; 26 int n, m; 27 int tot; 28 void add(int x, int y, int z) 29 { 30 tot++; 31 e[tot].to = y; 32 e[tot].weight = z; 33 e[tot].next = head[x]; 34 head[x] = tot; 35 } 36 void dfs(int x, int f) 37 { 38 p[x][0] = f; 39 deep[x] = deep[f] + 1; 40 for (int i = 1; (1 << i) <= deep[x]; i++) 41 p[x][i] = p[p[x][i - 1]][i - 1]; 42 for (int i = head[x]; i; i = e[i].next) 43 { 44 int to = e[i].to; 45 if (to != f) 46 { 47 dis[to] = dis[x] + e[i].weight; 48 dfs(to, x); 49 } 50 } 51 } 52 int lca(int x, int y) 53 { 54 if (deep[x] < deep[y]) 55 swap(x, y); 56 while (deep[x] > deep[y]) 57 x = p[x][(int)log2(deep[x] - deep[y])]; 58 if (x == y) 59 return y; 60 for (int k = (int)log2(deep[x]); k >= 0; k--) 61 if (p[x][k] != p[y][k]) 62 { 63 x = p[x][k]; 64 y = p[y][k]; 65 } 66 return p[x][0]; 67 } 68 int main() 69 { 70 cin >> n >> m; 71 for (int i = 1; i < n; i++) 72 { 73 int x, y, z; 74 cin >> x >> y >> z; 75 add(x, y, z); 76 add(y, x, z); 77 } 78 dfs(1, 0); 79 for (int i = 1; i <= m; i++) 80 { 81 int x, y; 82 cin >> x >> y; 83 int c = lca(x, y); 84 cout << dis[x] + dis[y] - 2 * dis[c] << endl; 85 } 86 return 0; 87 }