题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2473
题解:为每一个结点加一个虚根,这样每个结点都是叶子结点.插入结点时,把它们都并到虚根的集合中.删除结点时,只要把它的父结点置为一个无用的虚根。
#include <stdio.h>
#include <string.h>
#define MAXN 1000002
int father[MAXN<<1],flag[MAXN];
int Scan()
{
int res = 0, ch, flag = 0;
if((ch = getchar()) == '-')
flag = 1;
else if(ch >= '0' && ch <= '9')
res = ch - '0';
while((ch = getchar()) >= '0' && ch <= '9' )
res = res * 10 + ch - '0';
return flag ? -res : res;
}
int find(int x)
{
int i,j,r;
r=x;
while(r!=father[r])
r=father[r];
i=x;
while(i!=r)
{
j=father[i];
father[i]=r;
i=j;
}
return r;
}
void Union(int x,int y)
{
int fx=find(x);
int fy=find(y);
if (fx!=fy)
{
father[fx]=fy;
}
}
void init(int n,int m)
{
int i,MAX;
MAX=n+n+m;
for(i=0;i<n;++i)
father[i]=i+n;
for(i=n;i<MAX;++i)
father[i]=i;
}
int main()
{
int n,m,ans,i,id,x,y,cases=1;
char ch[5];
while(scanf("%d %d",&n,&m)&&(m+n)!=0)
{
init(n,m);
id=n+n;
for(i=0;i<m;++i)
{
scanf("%s",ch);
if(ch[0]=='M')
{
x=Scan();
y=Scan();
Union(x,y);
}
else
{
x=Scan();
father[x]=id++;
}
}
memset(flag,0,sizeof(flag));
ans=0;
for(i=0;i<n;++i)
{
x=find(i);
if(!flag[x])
{
ans++;
flag[x]=1;
}
}
printf("Case #%d: %d\n",cases++,ans);
}
return 0;
}