step1:首先需要一个数组来记录每个节点的映射的点,初始化时每个点都映射到自己身上。
step2:接着对每个输入的需要并操作的点进行并操作,并且将其中的一个根节点记录的节点数赋0,另一个为新的根节点,它的节点总数也需要更新。
step3:遇到需要删除的点的时候,首先找到这个点所在的树的根节点,让根节点记录节点的总数减1,将这个节点映射到一个新的节点(编号大于n),并初始化新节点的数据。
step4:遍历所有的点,若节点记录的节点数大于0,就让计数器自增1,最后计数器的数值就是所求的答案。
http://acm.hrbeu.edu.cn/index.php?act=problem&id=1006&cid=50
1 #include<stdio.h>
2 int f[2000],v[2000],son[2000],m,n; //f记录节点的父亲,v记录节点的映射,son记录子节点的数目
3 int find(int x)
4 {
5 if(f[x]!=x)
6 return f[x]=find(f[x]);
7 return x;
8 }
9 void make(int a,int b)
10 {
11 int f1=find(a);
12 int f2=find(b);
13 if(f1!=f2)
14 {
15 f[f1]=f2;
16 son[f2]+=son[f1];
17 son[f1]=0;
18 }
19 }
20 int main()
21 {
22 //freopen("in.txt","r",stdin);
23 int p=1;
24 while(scanf("%d%d",&n,&m)!=EOF)
25 {
26 if(n==0&&m==0) break;
27 int i,j,num=n;
28 for(i=0;i<n;i++)
29 {
30 f[i]=i;
31 v[i]=i;
32 son[i]=1;
33 }
34 while(m--)
35 {
36 char s;
37 getchar();
38 scanf("%c",&s);
39 if(s=='M')
40 {
41 int a,b;
42 scanf("%d%d",&a,&b);
43 make(v[a],v[b]);
44 }
45 else if(s=='S')
46 {
47 int a;
48 scanf("%d",&a);
49 int t=find(v[a]);
50 son[t]--; //删点
51 v[a]=num++;
52 f[v[a]]=v[a];
53 son[v[a]]=1;
54 }
55 }
56 int ans=0;
57 for(i=0;i<num;i++)
58 if(son[i]>0)
59 ans++;
60 printf("Case #%d: %d
",p++,ans);
61 }
62 return 0;
63 }