Junk-Mail Filter

最近在给新生上数据结构

于是复习(预习)了一下并查集

怎么有人给别人上课前才在学啊

(去年学了,但是摸太久了忘了)

给n个点m条操作

操作M:认为a和b属于一个集合

操作S:认为a不属于原来的集合

求有多少个集合

很明显是并查集

但是多了个删除单点的操作

设置虚拟节点

若原本1,2,3属于一个集合,设置一个虚拟节点5,原本123都指向5,现在使1出集合,就将1指向6

#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
int par[N]; //存储每个点的祖宗节点
int rank[N]; //树的高度
// 返回x的祖宗节点
int f[N];
void init(int n,int m)
{
	for (int i = 0; i <n; i ++ ) 
	{
		par[i] = i+n;// 初始化
		//rank[i]=0;
		f[i]=0;
	}
	for (int i = n; i <=n+n+m; i ++ ) 
	{
		par[i] = i;// 初始化
		//rank[i]=0;
		f[i]=0;
	}
}
int find(int x)
{
    if (par[x] == x) 
	{
		return x;
	}
	else
	{
		return par[x]=find(par[x]);
	}
}
void unite(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x==y) return ;
	par[x]=y;
//	if(rank[x]<rank[y])
//	{
//		par[x]=y;
//	}
//	else
//	{
//		par[y]=x;
//		if(rank[x]==rank[y])return rank[x]++;
//	}
}

bool same(int x,int y)
{
	return find(x)==find(y);
}
int main()
{
	int n,m;
	
	int a,b;
	char k;
		int cot=0;
	while(cin>>n>>m)
	{	
	if(n==0) break;
		init(n,m); 
		int z=n+n;
		for(int i=1;i<=m;i++) 
		{
			cin>>k;
			if(k=='M')
			{
			cin>>a>>b;
			// 合并a和b所在的两个集合:
			par[find(a)] = find(b);	
		}
		else
		{
			cin>>a;
			par[a]=z;
			z++;
		}
		}
		int tot=0;
		for(int i=0;i<n;i++) 
		{
			if(f[find(i)]==0)
			{
				f[find(i)]=1;
				tot++;
			}
		}

		printf("Case #%d: %d\n",++cot,tot);
	}
	
 } 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值