Time Limit: 1000MS Memory Limit: 20000K
Total Submissions: 7791 Accepted: 3698

本题是典型的并查集的做法,用sum[]存储以该点为祖先结点的集合的数目,用rank[]来存储树的高度,father[]用来存储每个节点的父亲节点。find()用来找当前节点所在集合的根节点.并且对路径进行压缩。union()用来合并两个集合,最好是按秩合并

代码:

 

1 #include<stdio.h>
2  int father[30005],rank[30005],sum[30005],f;
3  int find(int x)
4 {
5 if(x!=father[x])
6 {
7 father[x]=find(father[x]);
8 }
9 return father[x];
10 }
11 void Union(int x,int y)
12 {
13 if(x==y)
14 return ;
15 if(rank[x]>rank[y])
16 {
17 father[y]=x;
18 sum[x]=sum[x]+sum[y];
19 }
20 else
21 {
22 if(rank[x]==rank[y])
23 {
24 rank[y]++;
25 }
26 father[x]=y;
27 f=y; // 不要忘记这一句话,我就在这里吃了一次亏!f保存的是根节点。
28 sum[y]=sum[y]+sum[x];
29 }
30
31 }
32 int main()
33 {
34 int n,m,i,k,x,ff;
35 while(scanf("%d%d",&n,&m)!=EOF)
36 {
37 if(n==0 && m==0)
38 break;
39 for(i=0;i<n;i++)
40 {
41 father[i]=i;
42 rank[i]=0;
43 sum[i]=1;
44 }
45 while(m--)
46 {
47 scanf("%d",&k);
48 for(i=1;i<=k;i++)
49 {
50 scanf("%d",&x);
51 if(i==1)
52 f=find(x);
53 else
54 {
55 ff=find(x);
56 Union(f,ff);
57 }
58 }
59 }
60 f=find(0);
61 printf("%d\n",sum[f]);
62 }
63 return 0;
64 }
65