ZOJ 1789 水水的并查集,刚开始学会并查集,做了此题。经过一次失败后终于AC了哈哈~ AC感觉就是好啊!与大家共分享啊
#include<stdio.h>
#include<stdlib.h>
#define N 30000
#define M 500
int rank[N], father[N],num[N]; /* rank指代数的层数,num指每个节点数目 */
int Make_set(int x) /* 初始化父节点 */
{
int i;
for (i=0; i<x; i++)
{
father[i] = i;
rank[i] = 0;
num[i] = 1;
}
}
int Find_set(int x) /* 寻找父节点,运用递归查找 */
{
if (x != father[x])
father[x] = Find_set(father[x]);
return father[x];
}
int Union(int x,int y) /* 归并相同节点的树,并记录该节点的数目 */
{
x = Find_set(x);
y = Find_set(y);
if (rank[x] > rank[y])
{
father[y] = x;
num[x] += num[y];
}
else if(rank[x] < rank[y])
{
father[x] = y;
num[y] += num[x];
}
else if(x != y)
{
father[y] = x;
rank[x]++;
num[x] += num[y];
}
}
int main()
{
int i, k, b, p;
int n, m, a;
while(scanf("%d %d", &n,&m) != EOF)
{
if(n==0 && m==0) break;
Make_set(n);
while(m--)
{
scanf("%d", &k);
scanf("%d", &a);
for(i=1; i<k; i++)
{
scanf("%d", &b);
Union(a,b);
}
}
p = Find_set(0); /* 寻找0节点的位置 */
printf("%d\n", num[p]);
}
return 0;
}