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 :
求最小公共祖先有脱机和在线两种算法,<<算法艺术>>中有介绍,这题我用的是脱机最小公共祖先算法,速度快些。
求脱机最小公共祖先算法用到了并查集 ,算法描述如下:
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 for( int 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 for( int 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 for( int i=1;i<MAXN;i++ ) {
61 s[ i ].clear( );
62 tree[ i ].clear( );
63 }
64
65 for( int i=0;i<n;i++ ) {
66 cin>>node>>c1>>c2>>n1>>c3;
67 if( n1>0 ) {
68 for( int j=0;j<n1;j++ ) {
69 cin>>a;
70 tree[ node ].push_back( a );
71 br[ a ]=false;
72 }
73 }
74 }
75 for( int i=1;i<=n;i++ )
76 if( br[ i ] ) {
77 root=i;
78 break;
79 }
80
81 cin>>n1;
82 for( int 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 for( int i=1;i<=n;i++ ) {
90 if( total[ i ]>0 )
91 cout<<i<<":"<<total[ i ]<<endl;
92 }
93 }
94 return 0;
95 }
96
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 for( int 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 for( int 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 for( int i=1;i<MAXN;i++ ) {
61 s[ i ].clear( );
62 tree[ i ].clear( );
63 }
64
65 for( int i=0;i<n;i++ ) {
66 cin>>node>>c1>>c2>>n1>>c3;
67 if( n1>0 ) {
68 for( int j=0;j<n1;j++ ) {
69 cin>>a;
70 tree[ node ].push_back( a );
71 br[ a ]=false;
72 }
73 }
74 }
75 for( int i=1;i<=n;i++ )
76 if( br[ i ] ) {
77 root=i;
78 break;
79 }
80
81 cin>>n1;
82 for( int 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 for( int i=1;i<=n;i++ ) {
90 if( total[ i ]>0 )
91 cout<<i<<":"<<total[ i ]<<endl;
92 }
93 }
94 return 0;
95 }
96