并查集的删除需要一个数组来记录某点的真实对应节点,如果a点删除,则直接把a点的真实对应点指向一个新的b,这样原有的结构信息不会错乱。
这题需要统计有几个等价类。。。一直以为可以像以前一样通过parent等不等于-1判断TAT。其实只要开一个新的数组进行标记,每找到一个新的祖节点就标记一下就好,这样废弃的集合就不会被错算
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int parent[2000005];
int vis[2000005];
int mark[100005];
int num,n,m;
int root(int p)
{
if(parent[p]==-1) return p;
else return parent[p]=root(parent[p]);
}
void merge(int a,int b)
{
a=root(a);
b=root(b);
parent[a]=b;//在这里其实也可以设置一些值的传递
}
int main()
{
int R=0;
while(scanf("%d%d",&n,&m)!=EOF &&n!=0)
{
R++;
num=n;
int i,j,ta,tb,ans=0;
char ts[5];
memset(parent,-1,sizeof(parent));
memset(mark,-1,sizeof(mark));
memset(vis,0,sizeof(vis));
for(i=0;i<n;i++)
{
mark[i]=i;
}
for(i=1;i<=m;i++)
{
scanf("%s",ts);
if(ts[0]=='M')
{
scanf("%d%d",&ta,&tb);
if(root(mark[ta])!=root(mark[tb]))
merge(mark[ta],mark[tb]);
}
else
{
scanf("%d",&ta);
mark[ta]=num++;
}
}
for(i=0;i<n;i++)
{
ta=root(mark[i]);
if(vis[ta]==0)
{
vis[ta]=1;
ans++;
}
}
printf("Case #%d: %d\n",R,ans);
}
return 0;
}