1 条题解
-
1
预处理出表示点到根的距离,答案是
非常容易证明
代码如下
#include <bits/stdc++.h> using namespace std; int n, k, b[1000005], x, y, z, tot, h[500005], len[500005], fa[500005][33], dep[500005], lg[500005], f[1000005], ans; struct node { int to, next, w; } a[1000005]; void dfs(long long x, long long fn, long long l) { fa[x][0] = fn; dep[x] = dep[fn] + 1; len[x] = l; for (int i = 1; i <= 31; i++) { fa[x][i] = fa[fa[x][i - 1]][i - 1]; } for (int i = h[x]; i; i = a[i].next) { if (a[i].to != fn) { dfs(a[i].to, x, l + a[i].w); } } } int lca(int x, int y) { if (dep[x] < dep[y]) { swap(x, y); } while (dep[x] > dep[y]) { x = fa[x][lg[dep[x] - dep[y]] - 1]; } if (x == y) { return x; } for (int k = lg[dep[x]] - 1; k >= 0; k--) { if (fa[x][k] != fa[y][k]) { x = fa[x][k], y = fa[y][k]; } } return fa[x][0]; } void add(int x, int y, int z) { ++tot; a[tot].to = y; a[tot].next = h[x]; a[tot].w = z; h[x] = tot; } void answer(int x, int fn) { for (int i = h[x]; i; i = a[i].next) { if (a[i].to != fn) { answer(a[i].to, x); f[x] += f[a[i].to]; } } ans = max(ans, f[x]); } int main() { cin >> n; for (int i = 1; i <= n; ++i) { lg[i] = lg[i - 1] + (1 << lg[i - 1] == i); } for (int i = 1; i <= n - 1; i++) { cin >> x >> y >> z; add(x, y, z); add(y, x, z); } dfs(1, 0, 0); cin >> k; for (int i = 1; i <= k; i++) { cin >> x >> y; int t = lca(x, y); cout << len[x] + len[y] - 2 * len[t] << endl; } }
- 1
信息
- ID
- 7
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- 递交数
- 7
- 已通过
- 5
- 上传者