注意:两个城市之间可以有多条道路相通,也就是说
3 3
1 2
1 2
2 1
这种输入也是合法的
当N为0时,输入结束,该用例不被处理。
原题目链接:http://hdu.hustoj.com/showproblem.php?pid=1232
并查集:并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。(取自360百科)
虽然这题用我们以前的暴力也能解题,但是到数据过大的时候会超时,所以此处就考虑到了时间复杂度,所以要用并查集,大大的减少了输出答案所需要的时间。
该题其实很简单,应该算是并查集的入门题吧。
题目, 比如样例:
5 2 (n=5,m=2)
1 2 城镇1 2相连
3 5 城镇3 5相连 那么(1,2) (3,5) (4) 总共有3个集合,集合数目-1就是答案。
又比如说 1,3相连 3,5相连 5,7相连 3.9相连
用通俗的说法 3的父亲是1 5的父亲是3,5的爷爷是1, 7的父亲是5.....后面所有的与该相通的祖宗都是同一个。然后再后面的步骤中,将同一个祖宗的城镇,改值。
贴上代码:
#include<stdio.h>
int bin[1010];
int findx(int x)
{
int r=x;
while (bin[r]!=r) //改变原城镇的初始值
r=bin[r];
return r;
}
void merge(int x,int y)
{
int fx,fy;
fx=findx(x);
fy=findx(y);
if (fx!=fy)
bin[fx]=fy;
}
int main()
{
int n,m,x,y,i,ans;
while (scanf("%d%d",&n,&m)&&n)
{
for (i=1;i<=n;i++) //对城镇初始化
bin[i]=i;
if (m==0)
printf ("%d\n",n-1);
else{
for (;m>0;m--){
scanf ("%d%d",&x,&y);
merge(x,y);
}
for (ans=0,i=1;i<=n;i++)
if (bin[i]==i) // 计数 有几个城镇集合
ans++;
printf ("%d\n",ans-1);
}
}
return 0;
}