这是一个简单的并査集运用,每次案例开始,我们按照输入的N城市个数初始化:
初始化过程为,1到N的父亲节点为本身,1到N的rank深度为0,但是我们把rank[0]
作为要修建的道路数,初始化为N-1,比如我们初始化N为3的情况,rank[0]=2,一开始只要
修建两条路.....然后就是按照M输入M组联通城市,每次就和并一次,合并最后,我们就把
rank[0]减一,因为合并了两个城市之后,道路就少了一条。
基于这个题目,推荐一个一样的题目,就是poj2524 宗教的个数
这个链接是关于并査集的学习,我是一个小白,开始就是看了这里 http://wenku.baidu.com/view/f55a0d26aaea998fcc220e8f.html
下面是代码
#include<stdio.h>
int father[1005];//记录父亲节点
int rank[1005];//记录次节点的深度
void init(int n)
{
for(int i=1;i<=n;i++)
{
father[i]=i;
rank[i]=0;
}
rank[0]=n-1;
}
int find(int x)
{
if(x!=father[x])
father[x]=find(father[x]);
return father[x];
}
void Union(int x,int y)
{
if(x == y)
return ;
if(rank[x] > rank[y])//将深度浅的合并入深度大的集合中 可看链接 http://zh.wikipedia.org/zh-cn/%E5%B9%B6%E6%9F%A5%E9%9B%86
father[y]=x;
else
{
father[x]=y;
}
if(rank[x] == rank[y])
rank[y]++;
rank[0]--;//合并了一次,道路数就减一
}
int main()
{
int N,M;
int a,b;
while(scanf("%d",&N),N)
{
init(N);
scanf("%d",&M);
while(M--)
{
scanf("%d%d",&a,&b);
Union(find(a),find(b));
}
printf("%d\n",rank[0]);
}
return 0;
}