题目大意:
询问一棵树里 u 到 v 的距离
可由 dis[ u到根 ] + dis[ v到根 ] - 2*dis[ lca(u,v) ] 得到
https://blog.csdn.net/csyzcyj/article/details/10051173
#include <bits/stdc++.h> #define mem(i,j) memset(i,j,sizeof(i)) using namespace std; const int N=40005, Q=205; struct EDGE { int to, w, nt; }e[N<<1], q[Q<<1]; int head[N], tot, que[N], pos; // 题目数据可能有些问题 实际不止200个询问 WA了好多发 :( int fa[N], dis[N], lca[Q]; bool vis[N]; int n, m, U[Q], V[Q]; void init() { tot=1; mem(head,0); pos=1; mem(que,0); mem(vis,0); mem(dis,0); } void addE(int u,int v,int w) { e[tot].to=v, e[tot].w=w; e[tot].nt=head[u]; head[u]=tot++; } void addQ(int u,int v,int w) { q[pos].to=v, q[pos].w=w; q[pos].nt=que[u]; que[u]=pos++; } int getfa(int u) { if(fa[u]==u) return u; return fa[u]=getfa(fa[u]); } void Tarjan(int u) { fa[u]=u; vis[u]=1; for(int i=head[u];i;i=e[i].nt) { int v=e[i].to; if(!vis[v]) { dis[v]=dis[u]+e[i].w; Tarjan(v); fa[v]=u; } } for(int i=que[u];i;i=q[i].nt) { int v=q[i].to; if(vis[v]) lca[q[i].w]=getfa(v); } } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); init(); for(int i=1;i<n;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); addE(u,v,w); addE(v,u,w); } for(int i=1;i<=m;i++) { scanf("%d%d",&U[i],&V[i]); addQ(U[i],V[i],i), addQ(V[i],U[i],i); } Tarjan(1); for(int i=1;i<=m;i++) printf("%d ",dis[U[i]]+dis[V[i]]-2*dis[lca[i]]); } return 0; }