Problem Description
某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。
Input
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。当N为0时,输入结束,该用例不被处理。
Output
对每个测试用例,在1行里输出最小的公路总长度。
Sample Input
3
1 2 1
1 3 2
2 3 4
4
1 2 1
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5
0
Sample Output
3
5
最小生成树
- G= (V,E),若G的一个生成子图是一棵树,则称之为G的一棵生成树(记为T)。
- 最小生成树:无向图G的所有生成树中,树枝的权值总和最小的称为G的最小生成树
prim算法
-
算法思想:将各个点一一加入树中
-
具体做法:
-
先选择一个顶点作为树的根节点,把这个根节点当成一棵树
-
选择图中距离这棵树最近但是没有被树收录的一个顶点,把他收录在树中,并且保证不构成回路
-
按照这样的方法,把所有的图的顶点一一收录进树中。
-
如果没有顶点可以收录:
①如果图中的顶点数量等于树的顶点数量–>最小生成树构造完成
②如果图中的顶点数量不等于树的顶点数量–>此图不连通

对于上图,依次将元素1 -> 3 -> 6 -> 4 -> 2 -> 5加入集合可得到其最小生成树为:

再如使用prim算法的思想,依次将a -> b -> c -> i -> f -> g -> h-> d -> e点加入集合中,可构成如下图所示最小生成树:

Kruskal算法
- kruskal算法思想:
- 贪心: 先将所有的点加入集合,然后依次选取最短的边来组成一棵最小的生成树。n个顶点共有n - 1条边。
- 具体做法:
①将n个顶点看成n个集合。
②按权值由小到大的顺序选择边(先按照权值排序),且所选边应满足两个顶点不在同一个顶点集合内(不构成回路),将该边放到生成树边的集合中。同时将该边的两个顶点所在的顶点集合合并。
③重复②,直到所有的顶点都在同一个顶点集合内。
④可以使用并查集判断两个顶点是否在同一个顶点集合内

例,对于上图,使用Kruskal算法(依次加入边1-3,4-6,2-5,3-6,2-3),可以构成如下图所示的最小生成树:

样例分析
- 样例1 输出1 + 2 = 3

- 样例2 输出1 + 1 + 3 = 5

由以上两图不难发现,计算最小的公路总长度,采用Kruskal算法构建最小生成树即可
AC代码(kruskal算法)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 105;
const int M = 5010;
int parent[N];//disjoint set
struct edge
{
int a;//village a
int b;//village b
int dis;//distance of a and b
}nums[M];
bool cmp(edge u,edge v)
{
return u.dis < v.dis
最小生成树算法

本文介绍了解决最小公路总长度问题的最小生成树概念及其两种构建方法:Prim算法和Kruskal算法。通过Kruskal算法实现的具体代码示例,展示了如何处理村庄间的距离数据,以确定连接所有村庄所需的最短公路总长度。
最低0.47元/天 解锁文章
446

被折叠的 条评论
为什么被折叠?



