题意:
给你一棵树,让你求出树上的两个点之间的距离。
思路:
用LCA解决,求出两个节点到根节点的距离减去两倍的LCA到根节点的距离
#include "bits/stdc++.h"
using namespace std;
const int maxn = 40010;
int dp[2*maxn][30];
bool vis[maxn];
int ver[2*maxn], dept[2*maxn];
int first[maxn], dis[maxn];
struct edge {
int u,v,w,next;
} e[2*maxn];
int cnt,head[maxn];
int num;
void add(int u ,int v ,int w) {
e[num].u = u; e[num].v = v; e[num].w = w;
e[num].next = head[u]; head[u] = num++;
}
void dfs(int u ,int dep) {
vis[u] = true; ver[++cnt] = u; first[u] = cnt; dept[cnt] = dep;
for(int i = head[u]; i != -1; i = e[i].next) {
if(!vis[e[i].v]) {
int v = e[i].v , w = e[i].w;
dis[v] = dis[u] + w;
dfs(v,dep+1);
ver[++cnt] = u; dept[cnt] = dep;
}
}
}
void ST(int n) {
for(int i = 1; i <= n; i++) dp[i][0] = i;
for(int j = 1; (1<<j) <= n; j++) {
for(int i = 1; i+(1<<j)-1 <= n; i++) {
int a = dp[i][j-1], b = dp[i+(1<<(j-1))][j-1];
dp[i][j] = dept[a] < dept[b]?a:b;
}
}
}
int RMQ(int l,int r) {
int k=0;
while((1<<(k+1)) <= r-l+1) k++;
int a = dp[l][k], b = dp[r-(1<<k)+1][k];
return dept[a] < dept[b]?a:b;
}
int LCA(int u ,int v) {
int x = first[u] , y = first[v];
if(x > y) swap(x,y);
int res = RMQ(x,y);
return ver[res];
}
int main(int argc, char const *argv[])
{
int T;
scanf("%d", &T);
while(T--) {
int n, q;
num = 0;
scanf("%d%d", &n, &q);
memset(head, -1, sizeof(head));
memset(vis, false, sizeof(vis));
for(int i=1; i<n; i++) {
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
cnt = 0; dis[1] = 0;
dfs(1,1);
ST(2*n-1);
while(q--) {
int u,v;
scanf("%d%d",&u,&v);
int lca = LCA(u,v);
printf("%d\n",dis[u] + dis[v] - 2*dis[lca]);
}
}
return 0;
}