#include <iostream>
#include <algorithm>
#include<stdio.h>
#include<math.h>
using namespace std;
struct point
{
int root;
}c[1001];
int main()
{
int N,M,i,s,e,r;
while(scanf("%d",&N)!=EOF,N)//如果出现某个变量值不对,可能是scanf中%打成了&
{
scanf("%d",&M);
for(i=1;i<=N;i++)
{
c[i].root=i;//初始化城镇的根
}
while(M--)//一个语句错了最好检查所有语句,因为我喜欢复制粘贴,
{
scanf("%d %d",&s,&e);//使用逗号这样写虽然简便,但要注意会先执行一次scanf,然后再判断M是否为0
while(e!=c[e].root)
{
e=c[e].root;//找到根节点
}
while(s!=c[s].root)
{
s=c[s].root;//找到根节点
}
c[e].root=s;//注意并查集是集合为概念合并,以树的方式实现,注意当一个城镇出现多次对根赋值,如何保证根的唯一性
}//合并集合,应该把注意力集中到根节点上面,只要两个根节点并到一个集合内,两个集合就合并了
r=-1;//初始化r,前面当临时变量用了一下
for(i=1;i<=N;i++)
{
if(c[i].root==i)r++;
}
printf("%d\n",r);
}
return 0;
}
总结
1.如同while(scanf("%d",&n),n--),会先执行一次scanf,再判断n是否为零,相比while(n--)scanf("%d",&n);要多执行一次scanf