首页 > 代码库 > HDU 2473 Junk-Mail Filter 删点并查集

HDU 2473 Junk-Mail Filter 删点并查集

题目来源:HDU 2473 Junk-Mail Filter

题意:2中操作 M x, y 将x,y 合并到一个集合 S x 将x从所在的集合去掉 自己成为一个集合 最后求有多少个集合

思路:删点不好做 可以如果0 1 2在一个集合 可以定义个数组映射 就是每个点所对应实际的点 开始是a[0] = 0 a[1] = 1 a[2] = 2 说明都是自己

现在要去掉2 可以定义一个新的点 原来的要删的点留着 a[2] = 3 现在的3就是原来所对应的2 原来的集合堕落一个点 每次合并的时候处理a数组

#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1100010;
int f[maxn], a[maxn], flag[maxn];
int cnt;

void init(int n)
{
	for(int i = 1; i <= n; i++)
		f[i] = a[i] = i;
	cnt = n;
	memset(flag, 0, sizeof(flag));
}

int find(int x)
{
	if(x != f[x])
		return f[x] = find(f[x]);
	return f[x];
}

void merge(int x, int y)
{
	x = find(x);
	y = find(y);
	if(x != y)
		f[x] = y;
}
void del(int x)
{
	find(a[x]);
	f[++cnt] = cnt;
	a[x] = cnt;
}
int main()
{
	int cas = 1;
	int T;
	int n, m;
	while(scanf("%d %d", &n, &m) && (n||m))
	{
		init(n);
		while(m--)
		{
			char s[10];
			scanf("%s", s);
			if(s[0] == 'S')
			{
				int x;
				scanf("%d", &x);
				x++;
				del(x);
			}
			else
			{
				int x, y;
				scanf("%d %d", &x, &y);
				x++, y++;
				merge(a[x], a[y]);
			}
		}
		int ans = 0;
		for(int i = 1; i <= n; i++)
		{
			int x = find(a[i]);
			if(!flag[x])
			{
				ans++;
				flag[x] = 1;
			}
		}
		printf("Case #%d: %d\n", cas++, ans);
	}
	return 0;
}