poj 1330 Nearest Common Ancestors

这是一道找最近祖先的问题,我用的是纯暴力的方法。

#include<iostream>
#include<cstdio>
using namespace std;
int father[10024];
int father1[10024];
int father2[10024];
int main()
{
int n,T,f,s;
scanf( "%d",&T );
while( T-- )
{

scanf( "%d" ,&n );
for( int i=0;i<=n;i++ )
father[i]=i;
for( int i=1; i< n; i++ )
{
scanf( "%d%d" ,&f,&s );
father[s]=f;
}
scanf( "%d%d",&f,&s );
int i=f,j=0,k=0;
father1[j++]=f;
while( father[i]!=i )//记录f的所有祖先
{
father1[j++]=father[i];

// printf( "father[%d]=%d %d\n",i,father[i],i );

i=father[i];
// getchar();
}
father1[j++]=father[i];
i=s;
father2[k++]=s;
while( father[i]!=i )//记录s的所有祖先
{
father2[k++]=father[i];
i=father[i];
}

father2[k++]=father[i];
int flag=0;
for( int i=0;i<j; i++ )//祖先的匹配
{
if( flag ) break;
for( int t=0;t<k;t++ )
{
if( father1[i]==father2[t] )
{
printf( "%d\n",father2[t] );
flag=1;
break;
}
}
}
}
return 0;
}

第二种方法:

LCA;这个题好像比上种方法还要慢些;

#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
#include<vector>
using namespace std;
vector<int> tree[10024],Qes[10024];
int visit[10024],set[10024],indegree[10024],ancestor[10024];
void init( int n )
{
for( int i=0; i<= n; i++ )
{
visit[i]=0;
set[i]=i;
indegree[i]=0;
ancestor[i]=0;
tree[i].clear();
Qes[i].clear();
}
}
int find( int x )//查找函数,并压缩路径
{
return set[x]==x?x:set[x]=find( set[x] );
}
void Union( int a,int b )//合并函数
{
int X,Y;
X=find( a );
Y=find( b );
if( X!=Y )
{
set[Y]=X;
}
}
void LCA( int a )
{
ancestor[a]=a;
int size=tree[a].size();
for( int i=0; i< size; i++ )
{
LCA( tree[a][i] );
Union( a,tree[a][i] );
ancestor[ find( a ) ] = a; //让a的父节点祖先为a,因为是回溯操作,一定能保证集合的祖先是最近祖先  
}
visit[a]=1;
size=Qes[a].size( );
for( int i=0;i<size; i++ )
{//如果已经访问了问题节点,就可以返回结果了.
if( visit[Qes[a][i]]==1 )
{//如果这个点处理过,那么这个祖先就是共同祖先  
cout<<ancestor[find( Qes[a][i] )]<<endl;
return ;
}
}
}
int main( )
{
int Case,f,s,n;
scanf( "%d",&Case );
while( Case-- )
{

scanf( "%d" ,&n );
init( n );
for( int i=1; i<n; i++ )
{
scanf( "%d %d",&f,&s );
indegree[s]++;
tree[f].push_back( s );
}
scanf( "%d %d",&f,&s );
      //相当于询问两次
Qes[f].push_back( s );
Qes[s].push_back( f );
for( int i=1;i<=n ; i++ )
{//寻找根节点
if( indegree[i]==0 )
{
LCA( i );
break;
}
}
}
return 0;
}


 

posted @ 2012-01-07 09:47  wutaoKeen  阅读(168)  评论(0)    收藏  举报