码迷,mamicode.com
首页 > 编程语言 > 详细

HDU2473 - Junk-Mail Filter 利用虚拟数组实现删除并查集的节点

时间:2015-08-26 22:37:18      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:hdu   数据结构   并查集   

HDU2473 - Junk-Mail Filter: http://acm.hdu.edu.cn/showproblem.php?pid=2473

题目大意: M a b,代表a和b是同一类的,S a,代表原先给出的a的信息是错的,现在将其单独分成一类. 求最后一共有多少类邮件.

若只是分类,很直接就会想到并查集.但这里若直接用并查集是会出错的,因为删除的那个节点后面还可能会有其他的子节点,若直接把其删除,结果会出错. 这里就需要用到一个虚拟数组Trick,和Father数组合作,实现"删除"的目的(实际上该节点还是存在的).

代码: 

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 1000111*2;
int N,M;
int x,y;
int cnt,Case = 0,Ans;
int Trick[MAXN],Father[MAXN],Hash[MAXN];
void Initial()
{
	cnt = N;
    Ans = 0;
	for(int i = 0;i < MAXN;i++)//另开一个虚拟数组Trick,开始和Father储存一样的信息 
		Father[i] = Trick[i] = i,Hash[i] = 0;
}
int Find(int x)
{
	if(x == Father[x])return x;
	return Father[x] = Find(Father[x]);	
}
void Union(int x,int y)
{
	x = Find(x);
	y = Find(y);
	if(x != y)
		Father[y] = x;
}
void Delete(int x)
{
	Father[cnt] = cnt;//传进来的是Trick的信息,这里改变并不会影响x的子节点的查询 
	Trick[x] = cnt++;//更新后的信息在Trick里面,删除了x,表示x单独成为一个集合 
}
char op[5];
int main()
{
	while(~scanf("%d%d",&N,&M),N + M)
	{
		Initial();
		while(M--)
		{
			scanf("%s",op);
			if(op[0] == 'M')
			{
				scanf("%d%d",&x,&y);
				Union(Trick[x],Trick[y]);//传进去的是Trick里的信息,但查找合并的时候用的是Father,信息还是储存在Trick里,没有被破坏 
			}else{
				scanf("%d",&x);
				Delete(x);//删除x节点 
			}		
		}
		for(int i = 0;i < N;i++)//只有N个人是不会变的,查找一共被分成了几个集合 
		{
			x = Find(Trick[i]);
			if(!Hash[x])Hash[x] = 1,Ans++;
		}
		printf("Case #%d: %d\n",++Case,Ans);
	}
	return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU2473 - Junk-Mail Filter 利用虚拟数组实现删除并查集的节点

标签:hdu   数据结构   并查集   

原文地址:http://blog.csdn.net/p_rogrammer/article/details/48009427

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!