Description
小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上。有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花费太多精力。
已知从某个节点爬到其父亲节点要花费 c 的能量(从父亲节点爬到此节点也相同),他们想找出一条花费精力最短的路,以使得搞基的时候精力旺盛,他们找到你要你设计一个程序来找到这条路,要求你告诉他们最少需要花费多少精力
Input
第一行一个n,接下来n-1行每一行有三个整数u,v, c 。表示节点 u 爬到节点 v 需要花费 c 的精力。
第n+1行有一个整数m表示有m次询问。接下来m行每一行有两个整数 u ,v 表示两只虫子所在的节点
Output
一共有m行,每一行一个整数,表示对于该次询问所得出的最短距离。
Sample Input
3
1 0 1
2 0 1
3
1 0
2 0
1 2
Sample Output
1
1
2
HINT
1<=n<=50000, 1<=m<=75000, 0<=c<=1000
Source
Solution
倍增LCA
1 #include <bits/stdc++.h> 2 using namespace std; 3 struct edge 4 { 5 int v, w, nxt; 6 }e[100005]; 7 int fst[50005], q[50005], front, back; 8 int fa[17][50005], dis[50005], dep[50005]; 9 10 void addedge(int i, int u, int v, int w) 11 { 12 e[i] = (edge){v, w, fst[u]}, fst[u] = i; 13 } 14 15 int LCA(int u, int v) 16 { 17 if(dep[u] > dep[v]) swap(u, v); 18 for(int i = 16; ~i; i--) 19 if(dep[fa[i][v]] >= dep[u]) 20 v = fa[i][v]; 21 if(u == v) return u; 22 for(int i = 16; ~i; i--) 23 if(fa[i][u] != fa[i][v]) 24 u = fa[i][u], v = fa[i][v]; 25 return fa[0][u]; 26 } 27 28 int main() 29 { 30 int n, m, u, v, w; 31 cin >> n; 32 for(int i = 1; i < n; i++) 33 { 34 cin >> u >> v >> w; 35 addedge(i << 1, ++u, ++v, w); 36 addedge(i << 1 | 1, v, u, w); 37 } 38 q[++back] = 1, dep[1] = fa[0][1] = 1; 39 while(front != back) 40 { 41 u = q[++front]; 42 for(int i = fst[u]; i; i = e[i].nxt) 43 if(e[i].v != fa[0][u]) 44 { 45 q[++back] = e[i].v; 46 dep[e[i].v] = dep[u] + 1; 47 fa[0][e[i].v] = u; 48 dis[e[i].v] = dis[u] + e[i].w; 49 } 50 } 51 for(int i = 1; i <= 16; i++) 52 for(int j = 1; j <= n; j++) 53 fa[i][j] = fa[i - 1][fa[i - 1][j]]; 54 cin >> m; 55 while(m--) 56 { 57 cin >> u >> v, u++, v++; 58 cout << dis[u] + dis[v] - 2 * dis[LCA(u, v)] << endl; 59 } 60 return 0; 61 }
时间: 2024-11-19 16:46:15