题目链接:HDU-2473
主要思路:
初始时将所有点有与它的编号+n的点并在一起,合并时照常,删除从一个集合里删除一个点就是给这个点在给一个新的集合。最后统计每个点所在集合的个数即可(编号小于n)。注意要开n*2+m个集合(即fa数组的大小),否则getfa操作会出问题,预处理fa数组也是一样。
AC代码:
#include<cstdio>
#include<cstring>
#define M 100005
char s[10];
int fa[M*12];//n*2+m大于M*10
bool mark[M*12];
int getfa(int v){
if(fa[v]==v)return fa[v];
return fa[v]=getfa(fa[v]);
}
int main(){
int n,m,Case=0;
while(~scanf("%d%d",&n,&m)){
if(!n&&!m)return 0;
memset(mark,0,sizeof(mark));
for(int i=0;i<n;i++)fa[i]=i+n;//前面的数的fa都连到后面,这样从集合删除一个数时就不会把这个集合的数都删掉
for(int i=n;i<=n*2+m;i++)fa[i]=i;//如果右端点开小会MLE(fa数组为0,getfa是出错)
int cnt=n*2;
while(m--){
scanf("%s",s);
if(s[0]=='M'){
int a,b;
scanf("%d%d",&a,&b);
int x=getfa(a),y=getfa(b);
fa[x]=y;
}else{
int d;
scanf("%d",&d);
fa[d]=cnt++;//新开一个集合给他
}
}
int ans=0;
for(int i=0;i<n;i++){
int x=getfa(i);
if(!mark[x]){//判断这个集合有没有出现
ans++;
mark[x]=1;
}
}
printf("Case #%d: %d\n",++Case,ans);
}
}