其他分享
首页 > 其他分享> > Junk-Mail Filter

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);
	}
	
 } 

标签:Junk,int,查集,par,find,Filter,集合,Mail,节点
来源: https://blog.csdn.net/yeah17981/article/details/122529642