并查集之删除节点。。。
真的不想再天天做并查集了。。
这题目真是做不完。。
这一道一来又不会。。。
删除节点呢,具体的过程比较复杂,为了简单起见,
我们开始给节点初始化时,就给每个节点一个虚父节点
合并、找根的过程都不影响
而删除的时候,就把要删除的节点指向无意义的点
这样消失的不知不觉 也不会影响跟自己有关系的点。。。
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f
#define ll __int64
using namespace std;
int r[1200005],vis[1200050],n,m;
int root(int a)
{
if(r[a]==a) return a;
r[a]=root(r[a]);
return r[a];
}
void merge(int a,int b)
{
int ra,rb;
ra=root(a);
rb=root(b);
if(ra==rb) return ;
if(ra<rb) r[ra]=rb;
else r[rb]=ra;
}
int main()
{
int cnt=0,i,a,b,tmp,p,ans;
char s[10];
while(scanf("%d%d",&n,&m)&&(n||m))
{
cnt++;
for(i=0;i<n;i++)
r[i]=i+n;
for(i=n;i<n+n+m;i++)
r[i]=i;
p=n+n;
while(m--)
{
scanf("%s",s);
if(s[0]=='M')
{
scanf("%d%d",&a,&b);
merge(a,b);
}
else
{
scanf("%d",&a);
r[a]=p++;
}
}
ans=0;
memset(vis,0,sizeof vis);
for(i=0;i<n;i++)
{
tmp=root(i);
if(!vis[tmp])
{
ans++;
vis[tmp]=1;
}
}
printf("Case #%d: %d\n",cnt,ans);
}
return 0;
}