hdu2473 Junk-Mail Filter 并查集的删除

 本题考查的是并查集的删除.

在删除结点的时候要注意这样的问题: 并查集的结构是一棵树,当把某一个结点删去(将其父结点置为自己)时,它的子结点的根就会丢失.因此,在删除某结点的时候,要确定它的所有子结点都已经并到根上了.

解决方法: 为每一个结点加一个虚根,这样每个结点都是叶子结点.插入结点时,把它们都并到虚根的集合中.删除结点时,只要把它的父结点置为一个无用的虚根

http://blog.csdn.net/a181551981/article/details/6286007

#include <iostream> #include <string> using namespace std; int n,m,a,b,cnt,father[2000000],s[1000041],ans; int find(int x); void merge(int x,int y); //固定根节点,n+1~n+n作为根节点,而1~n作为虚拟根节点(指向n+1~n+n),之后在增添n+n~n+n+m作为备用节点 //删除时直接修改1~n指向的节点到n+n后的节点 int main(){ int Case = 1, n, m, i, a, b, ans; char ch; while(cin>>n>>m && (n||m)) { for(i = 0; i < n; i++) father[i] = i + n; for(i = n; i < n*2+m;i++) father[i] = i; cnt = 2 * n; ans = 0; memset(s, 0, sizeof(s)); while(m--) { cin>>ch; if(ch == 'M') { cin>>a>>b; merge(a, b); } else { cin>>a; father[a] = cnt++; } } for(i = 0; i < n; i++) { int temp = find(i); if(s[temp] == 0) { ans++; s[temp] = 1; } } cout<<"Case #"<<Case<<": "<<ans<<endl; Case++; } return 0; } int find(int x) { int temp = x,sum = 0,ans; while(temp != father[temp]) { temp = father[temp]; } ans = temp; while(x != ans) { temp = father[x]; father[x] = ans; x = temp; } return ans; } void merge(int a,int b) { int x = find(a); int y = find(b); if(x < y) father[y] = x; else if(x > y) father[x] = y; }

转载于:https://www.cnblogs.com/windmissing/archive/2012/01/25/2559859.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值