题意:
给你一棵树,让你求出树上的两个点之间的距离。
思路:
用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 ",dis[u] + dis[v] - 2*dis[lca]); } } return 0; }