Hdu2473 - Junk-Mail Filter - 并查集

这道题一开始本来想用直接改变p[i],使得p[i]=i,发现虽然路径压缩过了,但是实际上i下面所连接的点并没有压缩到i原本的根上,如图


而实际上应该是


所以就需要让1这个点依旧存在于这棵树里边,另外用一个变量来表示1这个点已经被删除掉


实际上右边的点一开始也是由sham构成的树,因为初始化的sham数组都为本身,只有当删除过某个点(图中为删除1点),那么sham[1]指向了原来不存在一个点,而右边的树里1还是没有改变,所以2的根依旧可以找到0,因为set的过程中都是set sham这一数组,所以再就不会寻找到sham[1]在右边的这棵树里。

  1. #include<stdio.h>  
  2. #include<string.h>  
  3. int sham[100010],p[1100010],flag[1100010],id;  
  4. int find(int n)  
  5. {  
  6.     if(p[n]!=n)  
  7.     {  
  8.         p[n]=find(p[n]);  
  9.     }  
  10.     return p[n];  
  11. }  
  12. void set(int x,int y)  
  13. {  
  14.     p[find(x)]=find(y);  
  15. }  
  16. void del(int x)  
  17. {  
  18.     sham[x]=id;  
  19.     p[sham[x]]=id;  
  20.     id++;  
  21. }  
  22. int main()  
  23. {  
  24.     int m,n;  
  25.     int cas=1;  
  26.     while(scanf("%d%d",&n,&m)!=EOF)  
  27.     {  
  28.         int cnt;  
  29.         if(n==0&&m==0)  
  30.         {  
  31.             break;  
  32.         }  
  33.         for(int i=0;i<n;i++)  
  34.         {  
  35.             sham[i]=p[i]=i;  
  36.         }  
  37.         char c[3];  
  38.         id=n;  
  39.         for(int i=0;i<m;i++)  
  40.         {  
  41.             scanf("%s",c);  
  42.             if(c[0]=='M')  
  43.             {  
  44.                 int x,y;  
  45.                 scanf("%d%d",&x,&y);  
  46.                 set(sham[x],sham[y]);  
  47.             }  
  48.             else   
  49.             {  
  50.                 int x;  
  51.                 scanf("%d",&x);  
  52.                 del(x);  
  53.             }  
  54.         }  
  55.         cnt=0;  
  56.         memset(flag,0,sizeof(flag));  
  57.         for(int i=0;i<n;i++)  
  58.         {  
  59.             int x=find(sham[i]);  
  60.             if(flag[x]==0)  
  61.             {  
  62.                 cnt++;  
  63.                 flag[x]=1;  
  64.             }  
  65.         }  
  66.         printf("Case #%d: %d\n",cas++,cnt);  
  67.     }  
  68. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值