您的位置:首页 > 其它

POJ1611(The Suspects)又见并查集

2011-10-05 13:59 585 查看
http://poj.org/problem?id=1611

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

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

贴代码:

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

int p
,f
;//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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: