Nearest Common Ancestors--POJ 1330

1、题目类型:LCA、并查集、DFS。

2、解题思路:最近公共祖先(Least Common Ancestors):对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u、v的祖先且x的深度尽可能大。步骤,(1)构造树形结构;(2)用并查集的方法求解LCA,DFS深度搜索树,搜索过程中记录其father节点,直到询问的两个节点找到为止;(3)由于此题只是询问一对节点的最近公共祖先,所以用flag记录其询问是否完成,可以减少运算时间。

3、注意事项:注意LCA函数、Find函数这种递归调用方式。

4、实现方法:

#include<iostream>
#include
<vector>
#define MAX 10010
using namespace std;

int n,flag;
int f[MAX],r[MAX],ancestor[MAX];
int indegreen[MAX],vis[MAX];
vector
<int> head[MAX],Que[MAX];

void Init()
{
int i,a,b;
cin
>>n;
flag
=0;
for(i=1;i<=n;i++)
{
head[i].clear();
Que[i].clear();
f[i]
=i;
r[i]
=1;
ancestor[i]
=0;
indegreen[i]
=0;
vis[i]
=0;
}
for(i=1;i<n;i++)
{
cin
>>a>>b;
head[a].push_back(b);
indegreen[b]
++;
}
cin
>>a>>b;
Que[a].push_back(b);
Que[b].push_back(a);
}

int Find(int u)
{
if(f[u]==u)
return f[u];
else
f[u]
=Find(f[u]);
return f[u];
}

void Union(int v,int u)
{
int a,b;
a
=Find(v);
b
=Find(u);
if(a==b)
return ;
if(r[a]<=r[b])
{
f[a]
=b;
r[b]
+=r[a];
}
else
{
f[b]
=a;
r[a]
+=r[b];
}
}

void LCA(int k)
{
int i,size;
size
=head[k].size();
ancestor[k]
=k;
for(i=0;i<size;i++)
{
if(flag)
break;
LCA(head[k][i]);
Union(k,head[k][i]);
ancestor[Find(k)]
=k;
}
vis[k]
=1;
size
=Que[k].size();
for(i=0;i<size;i++)
{
if(vis[Que[k][i]])
{
flag
=1;
cout
<<ancestor[Find(Que[k][i])]<<endl;
return ;
}
}
}

int main()
{
int T;
cin
>>T;
while(T--)
{
Init();
for(int i=1;i<=n;i++)
{
if(!indegreen[i])
{
LCA(i);
break;
}
}
}
return 0;
}

 

posted @ 2010-10-05 16:19  勇泽  阅读(1242)  评论(4编辑  收藏  举报