倍增求LCA
LCA函数返回(u,v)两点的最近公共祖先
#include <bits/stdc++.h> using namespace std; const int N = 40010*2; struct node { int v,val,next; node(){} node(int vv,int va,int nn):v(vv),val(va),next(nn){} }E[N]; int n,m; int tot,head[N],dis[N],f[N][20],dep[N]; void init() { tot = 0; memset(head,0,sizeof(head)); memset(dis,0,sizeof(dis)); memset(f,0,sizeof(f)); memset(dep,0,sizeof(dep)); } void add(int u,int v,int val) { E[++tot].next = head[u]; E[tot].v = v; E[tot].val = val; head[u] = tot; } void addEdge(int u,int v,int val) { add(u,v,val); add(v,u,val); } void dfs(int x,int fa) { f[x][0] = fa; for(int i=1;f[x][i-1];i++) f[x][i] = f[f[x][i-1]][i-1]; for(int i=head[x]; i; i=E[i].next) { int v = E[i].v; if(v != fa) { dis[v] = dis[x] + E[i].val; dep[v] = dep[x] + 1; dfs(v,x); } } } int lca(int u,int v) { if(dep[u] < dep[v]) swap(u,v); //int ans = dep[u] - dep[v]; for(int i=19;i>=0;i--) if(dep[u]-(1<<i)>=dep[v]) u = f[u][i]; for(int i=19;i>=0;i--) { if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];//ans+=(2<<i); } //if(u!=v) ans+=2; //return ans; if(u!=v) return f[u][0]; else return u; } int main () { //freopen("in.txt","r",stdin); int T; scanf("%d",&T); while (T--) { init(); scanf("%d %d",&n, &m); for(int i=1;i<=n-1;i++) { int u,v,val; scanf("%d %d %d",&u,&v,&val); addEdge(u,v,val); } dfs(1,0); // cout <<"yes" <<endl; while(m--) { int u,v; scanf("%d %d",&u,&v); int t = lca(u,v); printf("%d ",dis[u]+dis[v]-2*dis[t]); } } return 0; }