方法一:time limited:对于合并操作要搜遍全部元素
Code
//并查集
//方法一:用集合中最小元素标记集合。
//对于合并操作要搜遍全部元素。
#include<stdio.h>
int set[50001],n,m,a,b,caseno=0;
void init()
{
int i;
for(i=1;i<=n;i++){
set[i]=i;
}
}
int find1(int x)
{
return set[x];
}
void merge1(int a,int b)
{
int min,max,i;//记录a,b所在的集合中最小元素
min=find1(a)<find1(b)?find1(a):find1(b);
max=find1(a)>find1(b)?find1(a):find1(b);
for(i=1;i<=n;i++){
if(set[i]==max)
set[i]=min;
}
}
void output()
{
int ans=0,i;
for(i=1;i<=n;i++)
if(set[i]==i)
ans++;
printf("Case %d: %d\n",caseno,ans);
}
int main()
{
while(scanf("%d %d",&n,&m),n||m){
init();caseno++;
while(m--){
scanf("%d %d",&a,&b);
merge1(a,b);
}
output();
}
return 0;
}
方法二:
472K |
594MS |
GCC |
603B |
2009-01-23 12:47:28 |
Code
//并查集
//方法二:每个集合用一棵“有根树”表示
//set[i]=i,则i表示本集合,并是集合对应树的根
//set[i]=j,j<>i,则j是i的父节点
#include<stdio.h>
int set[50001],n,m,a,b,caseno=0;
void init()
{
int i;
for(i=1;i<=n;i++){
set[i]=i;
}
}
int find2(int x)
{
int r=x;
while(set[r]!=r)
r=set[r];
return r;
}
void merge2(int a,int b)
{
if(find2(a)<find2(b))
set[find2(b)]=find2(a);
else
set[find2(a)]=find2(b);
}
void output()
{
int ans=0,i;
for(i=1;i<=n;i++)
if(set[i]==i)
ans++;
printf("Case %d: %d\n",caseno,ans);
}
int main()
{
while(scanf("%d %d",&n,&m),n||m){
init();caseno++;
while(m--){
scanf("%d %d",&a,&b);
merge2(a,b);
}
output();
}
return 0;
}