hdu_2473 Junk-Mail Filter 并查集
这个题是一个比较不错的并查集,这也让我知道了,并查集,并非只有并和查得功能,而且,还可以删除点!!
原题连接:http://acm.hdu.edu.cn/showproblem.php?pid=2473
具体的解题思路是:
正常的并查集,删除节点时 是用一个数组index[]将其设置为一个新的数组,也就是删除节点相当于重新定义了一个节点,设置原来的那个无效。
上面说的好像不是很清楚,慢慢的看代码吧!
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
#define Max 1100005
int set[Max],index[Max];bool flag[Max];
int sum;
int find(int x)
{
while(x != set[x])
return set[x] = find(set[x]);
return set[x];
}
void unite(int a,int b)
{
int _a = find(a);
int _b = find(b);
set[_a] = _b;
}
int n,m;
void init()
{
for(int i = 0;i < Max;i++)
{
set[i] = i;
index[i] = i;
}
sum = n;
}
int main()
{
int cas = 1;
while(scanf("%d%d",&n,&m))
{
if(n == 0 && m == 0) break;
init();
char c[2];int a,b;
for(int i = 0;i < m;i++)
{
scanf("%s",c);
if(c[0] == 'M')
{
scanf("%d%d",&a,&b);
a = index[a];
b = index[b];
unite(a,b);
}else
{
scanf("%d",&a);
index[a] = sum;
sum++;
}
}
int re = 0;
memset(flag,0,sizeof(flag));
for(int i = 0;i < n;i++)
{
int a = find(index[i]);
while(!flag[a])
{
re++;flag[a] = 1;
}
}
printf("Case #%d: %d\n",cas++,re);
}
return 0;
}