POJ 1611 The Suspects (并查集)

 文章作者:ktyanny 文章来源:ktyanny 转载请注明,谢谢合作。 

ktyanny:a的第一道并查集。

题目描述:

有很多组学生,在同一个组的学生经常会接触,也会有新的同学的加入。但是SARS是很容易传染的,只要在改组有一位同学感染SARS,那么该组的所有同学都被认为得了SARS。现在的任务是计算出有多少位学生感染SARS了。假定编号为0的同学是得了SARS的。

解题思路---->显然并查集了。并查集的详细解释在可以点击 并查集(不相交集合)进行学习。采用num[]存储该集合中元素个数,并在集合合并时更新num[]即可。然后找出0所在的集合的根节点x,因此,num[x]就是answer了。

 

ac代码: 16MS C++

 

#include  < stdio.h > //by ktyanny
#include  < iostream >
using   namespace  std;

const   int  MAXN  =   30001 /* 结点数目上线 */
int  pa[MAXN];     /* p[x]表示x的父节点 */
int  rank[MAXN];     /* rank[x]是x的高度的一个上界 */
int  num[MAXN]; /* num[]存储该集合中元素个数,并在集合合并时更新num[]即可 */

void  make_set( int  x)
{ /* 创建一个单元集 */
    pa[x]  =  x;
    rank[x]  =   0 ;
    num[x]  =   1 ;
}

int  find_set( int  x)
{ /* 带路径压缩的查找 */
    
/* 保存待查找的数 */
    
int  r  =  x, temp;
    
/* 找到根节点 */
    
while (pa[r]  !=  r) r  =  pa[r];
    
while (x  !=  r)
    {
        temp  =  pa[x];
        pa[x]  =  r;
        x  =  temp;
    }
    
return  x;
    
// if(x != pa[x]) //注释掉的其实也是可以的,不过不想用递归来做啦
    
//     pa[x] = find_set(pa[x]);
    
// return pa[x];
}

/* 按秩合并x,y所在的集合 */
void  union_set( int  x,  int  y)
{
    x  =  find_set(x);
    y  =  find_set(y);
    
if (x  ==  y) return  ;
    
if (rank[x]  >  rank[y]) /* 让rank比较高的作为父结点 */
    {
        pa[y]  =  x;
        num[x]  +=  num[y];
    }
    
else  
    {
        pa[x]  =  y;
        
if (rank[x]  ==  rank[y])
            rank[y] ++ ;
        num[y]  +=  num[x];
    }
}

// answer to 1611 
int  main()
{
    
int  n, m, x, y, i, t, j;
    
while (scanf( " %d%d " & n,  & m))
    {
        
if (m == &&  n  ==   0 break ;
        
if (m  ==   0 )
        {
            cout  <<   " 1\n " continue ;
        }
        
for (i  =   0 ; i  <  n; i ++ )
            make_set(i);
        
for (i  =   0 ; i  <  m; i ++ )
        {
            scanf( " %d " & t);
            scanf( " %d " & x);
            
for (j  =   1 ; j  <  t; j ++ ){
                scanf( " %d " & y);
                union_set(x, y);
                x  =  y;
            }
        }
        x  =  find_set( 0 ); /* 找到0所在的树的树根 */
        
// int ans = 0;
        
// for(i = 0; i < n; i++)
        
//     if(pa[i] == x)
        
//         ans++;
        
// cout << ans << endl;
        cout  <<  num[x]  <<  endl;
    }
    
return   0 ;
}

 

 测试数据:

100 4

2 1 2

5 10 13 11 12 14

2 0 1

2 99 2

200 2

1 5

5 1 2 3 4 5

1 0 
0 0 
结果:
4
1
1


你可能感兴趣的:(poj)