1. 程式人生 > >【練習】小機房的樹

【練習】小機房的樹

namespace color dep std targe urn 最短路徑 oid i++

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 }

【練習】小機房的樹