LCA模板题。
DFS记录好,到根结点的距离。
#include <bits/stdc++.h> using namespace std; const int maxn = 40000+5; const int logmaxn = 20; struct Edge { int to,w; }; std::vector<Edge> G[maxn]; int f[maxn],dis[maxn],deep[maxn],p[maxn][20],n; struct LCA { int n; int fa[maxn]; int L[maxn]; int anc[maxn][logmaxn]; void preprocess() { for(int i=0; i<n; i++) { anc[i][0] = fa[i]; for(int j=1; (1<<j)<n; j++) anc[i][j] = -1; } for(int j=1; (1<<j)<n; j++) { for(int i=0; i<n; i++) { if(anc[i][j-1]!=-1) { int a = anc[i][j-1]; anc[i][j] = anc[a][j-1]; } } } } int query(int p,int q) { int log; if(L[p]<L[q]) swap(p,q); for(log = 1;(1<<log)<=L[p];log++); log--; for(int i=log;i>=0;i--) { if(L[p]-(1<<i)>=L[q]) { p = anc[p][i]; } } if(p==q) return p; for(int i=log;i>=0;i--) { if(anc[p][i]!=-1&&anc[p][i]!=anc[q][i]) { p = anc[p][i]; q = anc[q][i]; } } return fa[p]; } }sol; void dfs(int u,int pre,int t) { sol.L[u] = t; sol.fa[u] = pre; int num = G[u].size(); for(int i=0;i<num;i++) { int v = G[u][i].to; if(v!=pre) { dis[v] = dis[u] + G[u][i].w; dfs(v,u,t+1); } } } int main(int argc, char const *argv[]) { //freopen("in.txt","r",stdin); int t; scanf("%d",&t); while(t--) { int n,q; scanf("%d%d",&n,&q); for(int i=0;i<n;i++) G[i].clear(); sol.n = n; for(int i=0;i<n-1;i++) { int u,v,c; scanf("%d%d%d",&u,&v,&c); u--;v--; G[u].push_back((Edge){v,c}); G[v].push_back((Edge){u,c}); } dis[1] = 0; dfs(0,-1,0); sol.preprocess(); while(q--) { int a,b; scanf("%d%d",&a,&b); a--; b--; int lca = sol.query(a,b); printf("%d\n",dis[a]+dis[b]-2*dis[lca]); } } return 0; }
原文:http://www.cnblogs.com/TreeDream/p/7257827.html