题意:
N个点,形成一棵树,边有长度。
M个询问,每个询问(a,b),询问a和b的距离
思路:
模板题,看代码。DFS预处理算出每个结点离根结点的距离。
注意:
qhead[maxn],而不是qhead[maxm]。
输出用%I64d,不要用%lld。
C++ RE后 尝试用 G++交。
代码:
struct node{ int to,w,next,lca; }; int const maxn = 40005; int const maxm = 205; int fa[maxn]; int head[maxn], qhead[maxn]; int cnt1,cnt2; ll d[maxn]; ll res[maxm*2]; bool vis[maxn]; node edge[2*maxn]; node qedge[2*maxm]; int n,m; int findFa(int x){ return fa[x]==x?x:fa[x]=findFa(fa[x]); } inline void Addedge(int u,int v,int w){ edge[++cnt1].w=w, edge[cnt1].to=v, edge[cnt1].next=head[u], head[u]=cnt1; edge[++cnt1].w=w, edge[cnt1].to=u, edge[cnt1].next=head[v], head[v]=cnt1; } inline void Addqedge(int u,int v){ qedge[++cnt2].to=v, qedge[cnt2].next=qhead[u], qhead[u]=cnt2; qedge[++cnt2].to=u, qedge[cnt2].next=qhead[v], qhead[v]=cnt2; } void dfs(int u,int fa,ll w){ d[u]=w; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v==fa) continue; dfs(v,u,w+edge[i].w); } } void Tarjan_LCA(int u){ fa[u]=u, vis[u]=true; for(int i=head[u];i!=-1;i=edge[i].next){ if(!vis[edge[i].to]){ //防止访问到父亲 Tarjan_LCA(edge[i].to); fa[edge[i].to]=u; } } for(int i=qhead[u];i!=-1;i=qedge[i].next){ if(vis[qedge[i].to]){ qedge[i].lca=findFa(qedge[i].to); res[i]=d[u]+d[qedge[i].to]-2*d[qedge[i].lca]; } } } void init(){ rep(i,1,n) fa[i]=i; mem(head,-1); mem(qhead,-1); mem(vis,false); mem(d,0); mem(res,0); cnt1=cnt2=0; } int T,a,b,w; int main(){ cin>>T; while(T--){ scanf("%d%d",&n,&m); init(); rep(i,1,n-1){ scanf("%d%d%d",&a,&b,&w);; Addedge(a,b,w); } rep(i,1,m){ scanf("%d%d",&a,&b); Addqedge(a,b); } dfs(1,-1,0); Tarjan_LCA(1); for(int i=1;i<=cnt2;i+=2){ if(res[i]) printf("%I64d\n",res[i]); else printf("%I64d\n",res[i+1]); } } }
时间: 2024-10-10 00:01:41