【倍增求lca】小机房的树
2370 小机房的树
//讲真我觉得这题面有点恶心QAQ
大体思路:树上的最短路径一定经过两点lca, 预处理一个dis数组, 存每个点到根节点的距离, 两点(x, y) 之间的距离即为dis[x] + dis[y] - 2*dis[lca] ;
然后倍增求lca即可,dis数组在预处理每个点深度的时候一并处理
日常,“妙啊”
代码君qwq
1 #include<cmath> 2 #include<cstdio> 3 #include<iostream> 4 using namespace std; 5 const int maxn = 500050, maxm = 500050; 6 int n, m, s, num = 0, log2n; 7 int head[maxm], jump[maxn][23], dep[maxn], dis[maxn]; 8 struct edge { 9 int nxt, to, dis; 10 }e[maxm<<1]; 11 void add(int from, int to, int dis) { 12 e[++num].nxt = head[from]; 13 e[num].to = to; 14 e[num].dis = dis; 15 head[from] = num; 16 } 17 void dfs(int v) { 18 for(int i = head[v]; i; i = e[i].nxt) { 19 int u = e[i].to; 20 if(jump[v][0] != u) { 21 jump[u][0] = v; 22 dep[u] = dep[v] + 1; 23 dis[u] = dis[v]+e[i].dis; 24 dfs(u); 25 } 26 } 27 } 28 void init() { 29 /**/for(int i = 1; i <= log2n; i++) 30 for(int j = 1; j <= n; j++) 31 jump[j][i] = jump[jump[j][i-1]][i-1]; 32 } 33 int LCA(int x, int y) { 34 if(dep[x] < dep[y]) swap(x, y); 35 int t = dep[x] - dep[y]; 36 for(int i = 0; i <= log2n; i++) { 37 if(t&(1<<i)) x = jump[x][i]; 38 } 39 if(x == y) return x; 40 for(int i = log2n; i >= 0; i--) { 41 if(jump[x][i] != jump[y][i]) { 42 x = jump[x][i]; 43 y = jump[y][i]; 44 } 45 } 46 return jump[x][0]; 47 } 48 int main() { 49 scanf("%d", &n); 50 for(int i = 1; i < n; i++) { 51 int x, y, z; 52 scanf("%d%d%d", &x, &y, &z); 53 add(x, y, z), add(y, x, z); 54 } 55 s = 0; 56 log2n = log(n)/log(2)+1; 57 dep[s] = 1; 58 jump[s][0] = 0; 59 dis[s] = 0; 60 dfs(s); 61 init(); 62 scanf("%d", &m); 63 for(int i = 1; i <= m; i++) { 64 int x, y, ans = 0, lca; 65 scanf("%d%d", &x, &y); 66 lca = LCA(x, y); 67 ans = dis[x] + dis[y] - 2*dis[lca]; 68 printf("%d\n", ans); 69 } 70 return 0; 71 }
总之岁月漫长,然而值得期待。