1、倍增算法
#include<bits/stdc++.h>
#define MXN 50007
using namespace std;
std::vector v[MXN];//图
std::vector w[MXN];//边权
int fa[MXN][31], cost[MXN][31], dep[MXN];
//fa记录父节点 f[i][j] i的第2^j个祖先
//cost记录其权值
//dep记录深度
int n, m;
int a, b, c;
void dfs(int root, int fno) {//root要搜索的节点 fno父节点
fa[root][0] = fno;//root的父亲节点是fno
dep[root] = dep[fa[root][0]] + 1;//root的深度是父节点的深度+1
for (int i = 1; i < 31; ++i) {
fa[root][i] = fa[fa[root][i - 1]][i - 1];//计算祖先节点
cost[root][i] = cost[fa[root][i - 1]][i - 1] + cost[root][i - 1];
}
int sz = v[root].size();
for (int i = 0; i < sz; ++i) {//往下搜索
if (v[root][i] == fno) continue;
cost[v[root][i]][0] = w[root][i];
dfs(v[root][i], root);
}
}
int lca(int x, int y) {/求最近公共祖先
if (dep[x] > dep[y]) swap(x, y);
int tmp = dep[y] - dep[x], ans = 0;
for (int j = 0; tmp; ++j, tmp >>= 1)
if (tmp & 1) ans += cost[y][j], y = fa[y][j];
if (y == x) return ans;
for (int j = 30; j >= 0 && y != x; --j) {
if (fa[x][j] != fa[y][j]) {
ans += cost[x][j] + cost[y][j];
x = fa[x][j];
y = fa[y][j];
}
}
ans += cost[x][0] + cost[y][0];
return ans;
}
int main() {
memset(fa, 0, sizeof(fa));
memset(cost, 0, sizeof(cost));
memset(dep, 0, sizeof(dep));
scanf("%d", &n);
for (int i = 1; i < n; ++i) {
scanf("%d %d %d", &a, &b, &c);
++a, ++b;
v[a].push_back(b);
v[b].push_back(a);
w[a].push_back(c);
w[b].push_back(c);
}
dfs(1, 0);
scanf("%d", &m);
for (int i = 0; i < m; ++i) {
scanf("%d %d", &a, &b);
++a, ++b;
printf("%d\n", lca(a, b));
}
return 0;
}