zoj 1141 Closest Common Ancestors

就是求最小公共祖先
求最小公共祖先有脱机和在线两种算法,<<算法艺术>>中有介绍,这题我用的是脱机最小公共祖先算法,速度快些。
求脱机最小公共祖先算法用到了并查集 ,算法描述如下:

LCA(u)
    MAKE-SET(u)
    ancestor[FIND-SET(u)]   <-  u
    for each child  v of u  in T
       do LCA(v)
             UNION(u,v)
             ancestor[FIND-SET(u)]  <-  u
    color[u]  <-  BLACK
    for each node v  suck that  [u,v] belong P
       do if color[v]=BACL
          then print "The least common ancestor of"  u " and " v "is" ancestor[FIND-SET(v)]

可以证明对于每一对{u,v}belong P,最后一行恰执行一次.

my code :
 1 #include <iostream>
 2 #include <vector>
 3 using namespace std;
 4 
 5 #define BLACK true
 6 #define WHITE false
 7 
 8 const int MAXN=1000;
 9 
10 vector<int> tree[ MAXN+1 ];               //树的结构,所有儿子表示法
11 bool br[ MAXN+1 ];                        //标记数组,方便求出树的根
12 bool color[ MAXN+1 ];                     //LCA遍历中的标记数组
13 int ancestor[ MAXN+1 ];                   //最小公共祖先
14 int p[ MAXN+1 ],rank[ MAXN+1 ];           //并查集
15 int total[ MAXN+1 ];                      //存放结果
16 vector<int> s[ MAXN+1 ];                  //集合P
17 
18 void makeset( int x ) {
19     p[ x ]=x;
20     rank[ x ]=0;
21 }
22 int findset( int x ) {
23     if( x!=p[ x ] )
24     p[ x ]=findset( p[ x ] );
25     return p[ x ];
26 }
27 void link( int x,int y ) {
28     if( rank[ x ]>rank[ y ] )
29     p[ y ]=p[ x ];
30     else {
31     p[ x ]=p[ y ];
32     if( rank[ x ]==rank[ y ] )
33         rank[ y ]++;
34     }
35 }
36 
37 void LCA( int u ) {
38     makeset( u );
39     ancestor[ findset( u ) ]=u;
40     forint i=0;i<tree[ u ].size(  );i++ ) {
41     LCA( tree[ u ][ i ] );
42     link( u,tree[ u ][ i ] );
43     ancestor[ findset( u ) ]=u;
44     }
45     color[ u ]=BLACK;
46     forint i=0;i<s[ u ].size(  );i++ ) {
47     if( color[ s[ u ][ i ] ]==BLACK ) {
48         total[ ancestor[ findset( s[ u ][ i ] ) ] ]++;
49           }
50     }
51 }
52 
53 int main(  ) {
54     int n,n1,node,a,root,b;
55     char c1,c2,c3;
56     while(cin>>n) {
57     memset( br,true,sizeof br );
58     memset( color,WHITE,sizeof color );
59     memset( total,0,sizeof total );
60     forint i=1;i<MAXN;i++ ) {
61         s[ i ].clear(  );
62         tree[ i ].clear(  );
63     }
64 
65     forint i=0;i<n;i++ ) {
66         cin>>node>>c1>>c2>>n1>>c3;
67         if( n1>0 ) {
68         forint j=0;j<n1;j++ ) {
69             cin>>a;
70             tree[ node ].push_back( a );
71             br[ a ]=false;
72         }
73         }
74     }
75     forint i=1;i<=n;i++ )
76         if( br[ i ] ) {
77         root=i;
78         break;
79         }
80 
81     cin>>n1;
82     forint i=0;i<n1;i++ ) {
83         cin>>c1>>a>>c2>>b>>c3;
84         s[ a ].push_back( b );
85         s[ b ].push_back( a );
86     }
87 
88     LCA( root );
89     forint i=1;i<=n;i++ ) {
90         if( total[ i ]>0 )
91         cout<<i<<":"<<total[ i ]<<endl;
92     }
93     }
94     return 0;
95 }
96 


posted on 2007-07-21 16:37  woodfish  阅读(525)  评论(0编辑  收藏  举报

导航