1. 程式人生 > >hdu2586 /// tarjan離線求樹上兩點的LCA

hdu2586 /// tarjan離線求樹上兩點的LCA

oid csdn log span name pre amp hdu2586 edge

題目大意:

詢問一棵樹裏 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\n",dis[U[i]]+dis[V[i]]-2*dis[lca[i]]); } return 0; }

hdu2586 /// tarjan離線求樹上兩點的LCA