题目描述
某市调查城镇交通状况,得到现有城镇道路统计表。表中列出了每条道路直接连通的城镇。市政府 "村村通工程" 的目标是使全市任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要相互之间可达即可)。请你计算出最少还需要建设多少条道路?
输入格式
输入包含若干组测试测试数据,每组测试数据的第一行给出两个用空格隔开的正整数,分别是城镇数目 nn 和道路数目 mm ;随后的 mm 行对应 mm 条道路,每行给出一对用空格隔开的正整数,分别是该条道路直接相连的两个城镇的编号。简单起见,城镇从 11 到 nn 编号。
注意:两个城市间可以有多条道路相通。
输出格式
对于每组数据,对应一行一个整数。表示最少还需要建设的道路数目。
输入输出样例
输入 #1复制
4 2 1 3 4 3 3 3 1 2 1 3 2 3 5 2 1 2 3 5 999 0 0
输出 #1复制
1 0 2 998
说明/提示
数据规模与约定
对于 100\%100% 的数据,保证 1 \le n < 10001≤n<1000 。
上代码:
#include <bits/stdc++.h>
using namespace std;
int fa[1000001], n, m, x, y;
int find(int x)//并查集(路径压缩)
{
if(x != fa[x])//当x不等于它的爸爸时(当它是祖先时,它没有爸爸)
{
fa[x] = find(fa[x]);//继续找他的爸爸的爸爸
}
return fa[x];//返回祖先
}//查找
void unity(int x, int y)
{
int r1 = find(x);//找到x的祖先
int r2 = find(y);//找到y的祖先
fa[r1] = r2;//祖先和祖先结为父子(谁是父亲谁是儿子都可以)
}//合并
int main()
{
while(true)
{
int ans = 0;//ans要在循环中定义为0
scanf("%d", &n);
if(n == 0)
{
return 0;
}
scanf("%d", &m);
for(int i = 1; i <= n; i++)
{
fa[i] = i;//初始化自己的父亲是自己
}
for(int i = 1; i <= m; i++)
{
scanf("%d %d", &x, &y);
unity(x, y);//合并x和y
}
for(int i = 1; i <= n; i++)
{
if(find(i) == i)//自己的父亲等于自己本身
{
ans++;
}
}
printf("%d\n", ans - 1);//答案减一
}
return 0;
}