LCA应用求最短路
#include<cstdio> #include<iostream> #include<cstring> using namespace std; const int N=40005; int T,n,m,ans,tot; struct node{ int to,next,w; }edge[N<<1]; int head[N],dep[N]; int f[N][30],dis[N][30]; void init(){ tot=0; memset(edge,0,sizeof(edge)); memset(head,-1,sizeof(head)); memset(dep,0,sizeof(dep)); memset(dis,0,sizeof(dis)); } void add(int u,int v,int w){ edge[tot].to=v; edge[tot].next=head[u]; edge[tot].w=w; head[u]=tot++; } void dfs(int u,int fa){ f[u][0]=fa; dep[u]=dep[fa]+1; for(int j=1;(1<<j)<=dep[u];j++){ f[u][j]=f[f[u][j-1]][j-1]; dis[u][j]=dis[u][j-1]+dis[f[u][j-1]][j-1]; } for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v!=fa){ dis[v][0]=edge[i].w; dfs(v,u); } } } int lca(int u,int v){ if(dep[u]<dep[v]) swap(u,v); if(dep[u]!=dep[v]){ for(int j=20;j>=0;j--){ if(dep[f[u][j]]>=dep[v]){ ans+=dis[u][j]; u=f[u][j]; } } } if(u==v) return ans; for(int j=20;j>=0;j--){ if(f[u][j]!=f[v][j]){ ans+=dis[u][j]; ans+=dis[v][j]; u=f[u][j]; v=f[v][j]; } } return ans+dis[u][0]+dis[v][0]; } int main(){ scanf("%d",&T); while(T--){ init(); int n,m; scanf("%d%d",&n,&m); for(int i=1;i<n;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } dfs(1,0); for(int i=1;i<=m;i++){ ans=0; int x,y; scanf("%d%d",&x,&y); printf("%d\n",lca(x,y)); } } return 0; }