http://acm.pku.edu.cn/JudgeOnline/problem?id=2524
#include <iostream>//对并差集的不熟悉
#include <cstdio>
using namespace std;
long p[50010],n,m,tmp,rel[50010];
long getRoot(long big)//压缩路径+返回根结点
{
if(p[big]==big) return big;
else return p[big]=getRoot(p[big]);
}
int main()
{
long small,big,count=0,ans,i,bigRoot,smallRoot;
while(scanf("%ld%ld",&n,&m),(n||m))
{
for(i=1;i<=n;i++) p[i]=i;
while(m--)
{
scanf("%ld%ld",&small,&big);
if(small>big)
{
tmp=small;
small=big;
big=tmp;
}
if(p[big]==big) p[big]=small;
else
{
bigRoot=getRoot(big);
smallRoot=getRoot(small);?
//合并树的时候,需要找到根结点进行合并,
//每个点要看成一棵树的一部分,不断合并,而不能仅仅看成点
if(smallRoot<bigRoot) p[bigRoot]=smallRoot;
else p[smallRoot]=bigRoot;
}
}
for(i=1;i<=n;i++) getRoot(i);
memset(rel,0,sizeof(rel));
for(i=1;i<=n;i++) rel[p[i]]=1;
ans=0;
for(i=1;i<=n;i++) ans+=rel[i];
printf("Case %ld: %ld\n",++count,ans);
}
return 0;
}