洛谷P1536 村村通

.

P1536 村村通

    • 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
", ans - 1);
    }

    return 0;
}
 
原文地址:https://www.cnblogs.com/zbtrs/p/7073151.html