.
-
- 304通过
- 513提交
- 题目提供者JOHNKRAM
- 标签云端↑
- 难度普及/提高-
- 时空限制1s / 128MB
提交 讨论 题解
最新讨论更多讨论
- 求解 为什么这样的并查姿势…
- 为什么是并查集
题目描述
某市调查城镇交通状况,得到现有城镇道路统计表。表中列出了每条道路直接连通的城镇。市政府“村村通工程”的目标是使全市任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要相互之间可达即可)。请你计算出最少还需要建设多少条道路?
输入输出格式
输入格式:
每个输入文件包含若干组测试测试数据,每组测试数据的第一行给出两个用空格隔开的正整数,分别是城镇数目N(N<1000)和道路数目M;随后的M行对应M条道路,每行给出一对用空格隔开的正整数,分别是该条道路直接相连的两个城镇的编号。简单起见,城镇从1到N编号。
注意:两个城市间可以有多条道路相通。例如:
3 3 1 2 1 2 2 1 这组数据也是合法的。当N为0时,输入结束。
输出格式:
对于每组数据,对应一行一个整数。表示最少还需要建设的道路数目。
输入输出样例
输入样例#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
分析:判连通我们一般用并查集,如果这道题是有向图,那么可以先缩点,然后看有几个强连通分量,但是对于无向图而言要怎么操作呢?这个时候我们可以只需要找出每个点的祖先即可,有多少个不同的祖先,即有多少个不同的强连通分量,答案的个数为强连通分量的个数-1(连通n个点最少需要n-1条边)
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <queue> #include <stack> using namespace std; int n, m,fa[1010],ans; int find(int x) { if (x == fa[x]) return x; return fa[x] = find(fa[x]); } int main() { while (scanf("%d", &n) && n != 0) { ans = 0; for (int i = 1; i <= n; i++) fa[i] = i; scanf("%d", &m); for (int i = 1; i <= m; i++) { int x, y; scanf("%d%d", &x, &y); int fx = find(x), fy = find(y); fa[fx] = fy; } for (int i = 1; i <= n; i++) if (fa[i] == i) ans++; printf("%d\n", ans - 1); } return 0; }