假设你是电信实施工程师,需要为5个村庄架设通信网络做设计,即把这5个村庄都用电缆连接起来,要求用最小的成本来完成这项任务。村庄位置如下,连线之间数字表示村与村间可通达的直线距离,结点之间没有连线表示有高山或湖泊不予考虑。
这个网用邻接矩阵法表示为:
连接起这5个村庄至少要4条路径。显然,连通网(网的任意两个节点之间都有路径连接)的生成树(包含图中全部顶点,但只有足以构成树的n-1条边)满足要求,比生成树路径还多显然浪费了资源,那么这个问题就转换成如何求连通网的最小生成树。
主要有两种方法可以找到连通网的最小生成树,普里姆(Prim)法和克鲁斯卡尔(Kruskal)算法。
1.普里姆(Prim)算法
我们先用普里姆算法来求上述的问题吧。遍历过程如下:
-
a旁有3条边18、12、16,12最小我们走12的路径作为最小生成树的第一条边。
-
a和e两个顶点旁有其他边18、16、8、12,其中8最小,我们选择8作为最小生成树的第二条边。
-
a、e、b三个顶点旁有其他边16、21、22,16最小,我们选择16作为最小生成树的第三条边。
-
a、b、e、d四个顶点旁有其他边21、22、24其中21最小,我们选择21作为最小生成树的最后一条边。
可以求出最小千米数为:12+8+16+24=60.
从上述的例子可以得出普利姆法的思想:从连通网的任意一个结点开始,寻找已连通的结点的旁边权值最小的边(如果这条边连接已有的顶点则不算)连接的结点作为最小生成树的下一个结点,递归上述过程即可得到连通网的最小生成树。
2.克鲁斯卡尔(Kruskal)算法
普里姆算法是以某顶点为起点,逐步找个顶点上最小权值的边来构建最小生成树的。而卡鲁斯卡尔算法是从边的角度来构建最小生成树的。
首先通过邻接矩阵转为下图的边集数组,并按权值从小到大排序。
克鲁斯卡尔算法遍历过程如下:
- 权值8为最短边(b,e)。
-
权值12为最短边(a,e)。
-
权值16为最短边(a,d)。
- 权值18为最短边(a,b),但是a和b结点已经连通,因此选择权值为21的边(c,e)。
这样就找到了最小生成树,和普里姆法结果一致。
通过上述结果可以得出卡鲁斯卡尔算法的思想:找出连通网中未标记的权值最小的边(边的两个顶点都是已经标记边的顶点则不算)未作为最小生成树的边,并标记。递归上述过程即可得到结果。