题目:http://acm.hdu.edu.cn/showproblem.php?pid=1232
并查集详见http://blog.csdn.net/qq_29606781/article/details/47439437
#include<stdio.h>
int per[10100];
void init(int N)
{
int i;
for(i=1;i<=N;++i)
{
per[i]=i;
}
}
int find(int x)//根节点
{
int t=x;
while(per[t]!=t)
{
t=per[t];//更新节点
}
int r=t;//到根节点,注意节点r的父节点也是r
int i=x,j;
while(i!=r) //路径压缩
{
j=per[i]; //把下一个节点保存一下 ,也就是当前节点的父节点
per[i]=r;//把当前这个节点的父节点赋值为根节点
i=j;//更新节点
}
return r;//返回根节点
}
void join(int x,int y)//合并两个节点
{
int fx=find(x);
int fy=find(y);
if(fx!=fy)//如果x,y的根节点不同
{
per[fx]=fy;//把两个根节点连接
//至于哪个和哪个节点连接,看深度,可以开个数组,把深度小的连到深度大的
//这是一种优化方式,数据大的时候可以用
}
}
int main()
{
int n,m,i,x,y,cnt;
while(scanf("%d",&n),n)
{
cnt=0;
init(n);//初始化
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&x,&y);
join(x,y);
}
for(i=1;i<=n;++i)
{
if(per[i]==i)
{
++cnt;//到根节点的个数,即有几个集合
}
}
printf("%d\n",cnt-1);
}
return 0;
}
//递归压缩路径, 有高度优化
//时间:31
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#define maxn 1100
#define INF 0x3f3f3f3f
using namespace std;
int per[1100];
int ran[1100]; //ran:深度
int n, m;
void init(){
for(int i = 1; i <= n; ++i){
per[i] = i;
ran[i] = 0;
}
}
int find (int x){
if(x == per[x])
return x;
return per[x] = find(per[x]);
}
void jion (int x, int y){
int fx = find(x);
int fy = find(y);
if(fx == fy)
return ;
if(ran[fx] < ran[fy])//将深度小的树合并到深度大的数假设两棵树的深度分别是h1,h2
per[fx] = fy;//则合并后的数的高度h:max(h1,h2),if h1<>h2
else{ //h1+h2,if h1=h2
per[fy] = fx;
if(ran[fx] == ran[fy]) ran[fx]++;
}
}
int main (){
while(scanf("%d", &n),n){
scanf("%d", &m);
init();
int a, b;
while(m--){
scanf("%d%d", &a, &b);
jion(a,b);
}
int ans = 0;
for(int i = 1; i <= n; ++i){
if(per[i] == i)
ans++;
}
printf("%d\n", ans - 1);
}
return 0;
}