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


你可能感兴趣的:(close)