垃圾邮箱过滤器

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\n",p++,ans);
61     }
62     return 0;
63 }

 

 

posted @ 2014-03-01 12:55  清风旋叶  阅读(240)  评论(0编辑  收藏  举报