IT民工
加油!

http://poj.org/problem?id=1611

这貌似我做的第二道并查集的题,算是一道水题吧,题目的大概意思是找出与编号为0的人有

交集的人数。所以要将出现的集合中有交集的合并成大集合,最后输出0所在集合的人数。

 

贴代码:

 

#include<iostream>
using namespace std;
#define N 30005

int p[N],f[N];//f用来存集合元素的个数

int find(int x)//并查集的根本,找父亲结点
{
return p[x] == x ? x : ( p[x] = find(p[x]) );
}

void merge(int a, int b)
{
int x = find(a);
int y = find(b);
/*照顾0,所以把小的数作为父亲结点*/
if(x < y) {
p[y] = x;
f[x] += f[y];
}
else if(x > y) { //这里不能写else,因为x=y无需处理
p[x] = y;
f[y] += f[x];
}
}

int main()
{
int n,m;
int k,a,b;
while(cin >> n >> m,n || m)
{
/*初始化并查集 */
for(int i = 0; i < n; i++)
{
p[i] = i;
f[i] = 1;
}
while( m--)
{
cin >> k;
cin >> a;
for(int j = 1; j < k; j++)
{
cin >> b;
merge(a,b);//合并集合
}
}
cout << f[0] << endl;//输出0所在集合元素个数
}
return 0;
}


   
可能是merge函数写的不够好,所以跑了63ms...

 现在又写了一遍:

/*Accepted    408K    0MS    C++    927B    2012-07-27 16:24:33*/
#include<cstdio>

const int MAXN = 300101;
int p[MAXN], cnt[MAXN];

int find_set( int x)
{
    return p[x] = p[x] == x ? x : find_set(p[x]);
}

void union_set( int x, int y)
{
    int nx = find_set(x), ny = find_set(y);
    if( nx < ny){ //以编号小的点为根
        p[ny] = nx;
        cnt[nx] += cnt[ny];
    }
    else if(nx > ny) {
        p[nx] = ny;
        cnt[ny] += cnt[nx];
    }
}

int main()
{
    int n, m, k;
    while( scanf( "%d%d", &n, &m), n || m)
    {
        for( int i = 0; i < n; i ++)
        {
            p[i] = i;
            cnt[i] = 1;
        }
        while( m --)
        {
            int x, y;
            scanf( "%d", &k);
            scanf( "%d", &x);
            for( int i = 1; i < k; i ++)
            {
                scanf( "%d", &y);
                union_set(x, y);
            }
        }
        printf( "%d\n", cnt[0]);
    }
    return 0;
}
posted on 2011-10-05 13:59  找回失去的  阅读(203)  评论(0)    收藏  举报