LCA离线算法,递归求解。详见:http://blogold.chinaunix.net/u3/105033/showart_2238641.html
伪代码:
LCA(u)
{
Make-Set
(u);
ancestor[Find-Set
(u)]=u;
for every child v of u
{
LCA(v);
Union
(u,v);
}
color
[u]=colored;
for every questioned pair (u,v)
{
if color[v]==colored
{
the lca of (u,v) is ancestor[Find-Set
(v)];
}
}
}
#include<iostream> #include<cstdio> using namespace std; int tree[10001][100],in[10001],p[10001]; int cas,s,t; int n,q1,q2; bool vis[10001]; void Make_Set(int t) { p[t]=t; } int Find(int t) { if(t!=p[t]) p[t]=Find(p[t]); return p[t]; } void Union(int u,int v) { p[v]=u; } void LCA(int root) { Make_Set(root); int i; for(i=1;i<=tree[root][0];i++) { LCA(tree[root][i]); Union(root,tree[root][i]); } vis[root]=1; if(root==q1&&vis[q2]) printf("%d\n",p[Find(q2)]); else if(root==q2&&vis[q1]) printf("%d\n",p[Find(q1)]); } int main() { scanf("%d",&cas); while(cas--) { int i; memset(tree,0,sizeof(tree)); memset(in,0,sizeof(in)); memset(vis,0,sizeof(vis)); scanf("%d",&n); for(i=1;i<n;i++) { scanf("%d%d",&s,&t); tree[s][++tree[s][0]]=t; in[t]++; } scanf("%d%d",&q1,&q2); for(i=1;i<=n;i++) { if(in[i]==0) break;//根节点 } LCA(i); } return 0; }