1.问题
有6个村庄,共有10条路,各道路长度如下图,分别用Prim算法和Kruskal算法求连通6个村庄的最短路径长度。
2.解析
1. Prim算法构造最小生成树
-
加点:从一个顶点a开始,把顶点a加入最小生成树的集合U中,每次迭代选择与集合U中的点相连的权重最小的边对应的点,加入集合U中,继续迭代直到所有顶点都在集合U中。
-
构造步骤如下:
1)假设从顶点v0开始,发现边(v0,v1)的权重最小,U={0,1},输出边:v0----v1
2)此时与U中元素相连的权重最小的边为(v0,v2),U={0,1,2},输出边:v0----v2
3)此时与U中元素相连的权重最小的边为(v2,v3),U={0,1,2,3},输出边:v2----v3
4)此时与U中元素相连的权重最小的边为(v3,v5),U={0,1,2,3,5},输出边:v3----v5
5)此时与U中元素相连的权重最小的边为(v5,v4),U={0,1,2,3,4,5},输出边:v5----v4。此时所有边都在集合U中,最小生成树建立完成。 -
各步骤图解如下:
2.Kruskal算法构造最小生成树
-
加边:去掉所有边,将边按权重从小到大的顺序添加到图中,保证添加的过程中不会形成环,,添加至所有顶点相连即可,即最小生成树的边数为顶点数-1。
-
构造步骤如下:
1)最短边为(v4,v5),输出边:v4----v5
2)接下来是权重为2的边,对于权重相同的边,添加无先后顺序,只要不形成环即可,若先加(v3,v5),输出边:v3----v5
3)加入边(v0,v1),输出边:v0----v1
4)同2)理,加边(v0,v2),输出边:v0----v2
5)加边(v2,v3),输出边:v2----v3。此时生成树的边数为6-1,最小生成树建立完成。 -
各步骤图解如下:
3.设计
1. Prim算法
1)用二维数组dis[ ][ ]来存储边的权重,一维数组vis[ ]标记顶点是否已被放入最小生成树,用一个整型的vector数组mst作为最小生成树的顶点集合
2)构造一个prim( )函数来遍历寻找与已在最小生成树中的顶点相连的权重最小的边,将边对应的另一顶点存入mst,标记该点已被放入,并输出该边的两个顶点
3)当mst中的元素个数等于输入的顶点个数时,程序结束,最小生成树建立完成
2. Kruskal算法
1)用结构体存储边,并将边按权重从小到大排序
2)利用并查集来保证边不成环,按边权重从小到大遍历,若两点的父亲不同,即不会成环,则则将两点构成父子关系,加入并查集并输出边,边数cnt+1
3)当cnt==n-1时,程序结束,最小生成树建立完成
4.分析
Prim算法:O(n^2)
Kruskal算法:O(mlogm)
5.源码
GitHub地址:https://github.com/SUSUSU818/Algorithm/tree/master/homework_1
输入:
6 10
0 1 2
0 2 3
0 3 5
1 2 5
1 4 4
2 3 3
2 4 4
2 5 6
3 5 2
4 5 1
1.Prim算法
输出:
2.Kruskal算法
输出: