推荐博客:http://kmplayer.iteye.com/blog/604518
poj 1330
源代码:
#include <stdio.h>
#include <vector>
#define MAXN 10005
using namespace std;
vector<int>tree[MAXN];
vector<int>query[MAXN];
int n,q;
int s,t,cas;
int f[MAXN],visit[MAXN]; //MAXN为节点编号的最大值
int degree[MAXN]; //记录入度
int ancestor[MAXN]; //记录某一个并查集的祖先
int r[MAXN]; //深度
void Init()
{
for(int i=1;i<=n;i++)
{
r[i]=1;
visit[i]=0;
f[i]=i;
ancestor[i]=i;
degree[i]=0;
tree[i].clear();
query[i].clear();
}
}
int find(int x)
{
if(x==f[x]) return x;
else
{
f[x]=find(f[x]);
return f[x];
}
}
int Uion(int x,int y) //合并成功返回1,合并不成功返回0
{
int a=find(x);
int b=find(y);
if(a==b) return 0;
if(r[a]>r[b])
{
r[a]+=r[b];
f[b]=a;
}
else
{
r[b]+=r[a];
f[a]=b;
}
return 1;
}
void lca(int u)
{
for(int i=0;i<tree[u].size();i++)
{
lca(tree[u][i]);
Uion(tree[u][i],u);
ancestor[find(u)]=u;
}
visit[u]=1;
for(int i=0;i<query[u].size();i++)
{
if(visit[query[u][i]]==1)
{
printf("%d\n",ancestor[find(query[u][i])]);
}
}
}
int main()
{
freopen("D:\\a.txt","r",stdin);
scanf("%d",&cas);
while(cas--){
scanf("%d",&n);
Init();
for(int i=1;i<n;i++)
{
scanf("%d %d",&s,&t); //s[i]是父节点,t[i]是子节点
tree[s].push_back(t);
degree[t]++;
}
//scanf("%d",&q);
// for(int i=0;i<q;i++)
// {
scanf("%d %d",&s,&t); //查询s,t的最近公共祖先
query[s].push_back(t);
query[t].push_back(s);
// }
for(int i=1;i<=n;i++)
{
if(degree[i]==0)
{
lca(i);
break;
}
}
}
return 0;
}