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 ;
}

 

你可能感兴趣的:(REST)