\qquad 在上篇文章中,我介绍了网络模型中的一些相关概念,在这篇文章,我将介绍网络模型中的最小生成树算法,又叫最小支撑树算法。
最小生成树(最小支撑树)算法
0 原理
最小生成树算法的作用是连接一个网络的所有节点,使树上边的总长度达到最小。
两个例子:
- 需要在几个城镇之间修路,使得任意两个城镇都有路相连,中间可以穿过一个或者多个其他城镇,这时需要一个修路方案使修路的里程最小。
- 某海湾上需要设计一个海面上的天然气管道网路,将各个井口连接到岸边的运输点,设计的目标是最小化修建管道的费用。
最小生成树算法原理其实很简单:把节点分为已连接节点、未连接节点,在未连接节点中选一个节点 t t t,使得 t t t到已连接节点中某个节点的弧长最小。其实主要使用的思想还是贪心思想,从第一个节点开始,每次从未选节点中选一个节点,让该节点到已选节点中的路径最短,并将另一端的节点放入已选接节点中。
1 步骤
最小生成树的具体步骤是:
<1> 令N={1, 2, …, n},为网络中节点的集合,定义:
C
k
=
在
第
k
步
时
已
连
接
的
节
点
集
合
C
k
‾
=
在
第
k
步
以
后
需
要
连
接
的
节
点
集
合
(
未
连
接
或
待
连
接
的
节
点
)
C_k=在第k步时已连接的节点集合 \\ \overline{C_k}=在第k步以后需要连接的节点集合(未连接或待连接的节点)
Ck=在第k步时已连接的节点集合Ck=在第k步以后需要连接的节点集合(未连接或待连接的节点)
<2> 第0步:令 C 0 = ∅ , C 0 ‾ = N C_0=\emptyset,\overline{C_0}=N C0=∅,C0=N.
<3> 第1步:从 C 0 ‾ \overline{C_0} C0中的任意一个节点 i i i开始,令 C 1 = { i } C_1=\{i\} C1={i},那么 C 1 ‾ = N − { i } \overline{C_1}=N-\{i\} C1=N−{i}.设定 k = 2 k=2 k=2.
<4> 一般的第
k
k
k步:在还没连接的节点集合
C
‾
k
−
1
\overline{C}_{k-1}
Ck−1中选择一个节点
t
∗
t^*
t∗,使得
t
∗
t^*
t∗到
C
‾
k
−
1
\overline{C}_{k-1}
Ck−1中某个节点之间的弧长最小,然后将
t
∗
t^*
t∗放入
C
k
−
1
C_{k-1}
Ck−1中,并将
t
∗
t^*
t∗从
C
‾
k
−
1
\overline{C}_{k-1}
Ck−1中删除,即:
C
k
=
C
k
−
1
+
{
t
∗
}
C
k
‾
=
C
‾
k
−
1
−
{
t
∗
}
C_k = C_{k-1} + \{t^*\} \\ \overline{C_k} = \overline{C}_{k-1} - \{t^*\}
Ck=Ck−1+{t∗}Ck=Ck−1−{t∗}
<5> 停止条件:如果未连接节点的集合
C
k
‾
\overline{C_k}
Ck是空集,则停止。否则,设定
k
=
k
+
1
k=k+1
k=k+1,重复<4>。
2 栗子
某地的5个城镇需要铺设天然气管道,下图中给出了5个城镇之间可以铺设管道的情况的以及距离,先求一个设计方案,用最短的管道将5个城镇连接起来。
解题过程:
\qquad
从节点1开始(可以选择其他任意一个节点),则
C
1
=
{
1
}
,
C
1
‾
=
{
2
,
3
,
4
,
5
,
6
}
C_1=\{1\},\overline{C_1}=\{2,3,4,5,6\}
C1={1},C1={2,3,4,5,6}.下图中将为连接的点与已连接的点分为两个区域,并用线表示所有连接集合
C
1
,
C
1
‾
C_1,\overline{C_1}
C1,C1的侯选边,其中,红线表示的是所有候选边中最短的一条,令集合R存储每次选取的弧。开始迭代。
迭代1: 由图可见,边(1,2)是所有候选边中最短的一条,则确定节点2为下一连接节点,得到 C 1 = { 1 , 2 } , C 1 ‾ = { 3 , 4 , 5 , 6 } , R 1 = { ( 1 , 2 ) } C_1=\{1,2\},\overline{C_1}=\{3,4,5,6\},R_1=\{(1,2)\} C1={1,2},C1={3,4,5,6},R1={(1,2)}
迭代2: 边(2,5)是所有候选边中最短的,则确定节点3为下一连接节点,得到
C
2
=
{
1
,
2
,
5
}
,
C
2
‾
=
{
3
,
4
,
6
}
,
R
2
=
{
(
1
,
2
)
,
(
2
,
5
)
}
C_2=\{1,2,5\},\overline{C_2}=\{3,4,6\},R_2=\{(1,2),(2,5)\}
C2={1,2,5},C2={3,4,6},R2={(1,2),(2,5)}.其中,黑线表示已经连接的边。
迭代3: 边(2,4)是所有候选边中最短的,则确定节点4为下一连接点,得到
C
3
=
{
1
,
2
,
5
,
4
}
,
C
3
‾
=
{
3
,
6
}
,
R
3
=
{
(
1
,
2
)
,
(
2
,
5
)
,
(
2
,
4
)
}
C_3=\{1,2,5,4\},\overline{C_3}=\{3,6\},R_3=\{(1,2),(2,5),(2,4)\}
C3={1,2,5,4},C3={3,6},R3={(1,2),(2,5),(2,4)}.
迭代4: 边(4,6)是所有候选边中最短的,则确定节点6为下一连接点,得到
C
4
=
{
1
,
2
,
5
,
4
,
6
}
,
C
4
‾
=
{
3
}
,
R
4
=
{
(
1
,
2
)
,
(
2
,
5
)
,
(
2
,
4
)
,
(
4
,
6
)
}
C_4=\{1,2,5,4,6\},\overline{C_4}=\{3\},R_4=\{(1,2),(2,5),(2,4),(4,6)\}
C4={1,2,5,4,6},C4={3},R4={(1,2),(2,5),(2,4),(4,6)}.
迭代5: 边(1,3)和边(4,3)是所有候选边中最短的任选其中的一条,这里我们选(1,3),则确定节点3为下一连接点,得到
C
5
=
{
1
,
2
,
5
,
4
,
6
,
3
}
,
C
5
‾
=
{
}
,
R
5
=
{
(
1
,
2
)
,
(
2
,
5
)
,
(
2
,
4
)
,
(
4
,
6
)
,
(
1
,
3
)
}
C_5=\{1,2,5,4,6,3\},\overline{C_5}=\{\},R_5=\{(1,2),(2,5),(2,4),(4,6),(1,3)\}
C5={1,2,5,4,6,3},C5={},R5={(1,2),(2,5),(2,4),(4,6),(1,3)}.
最终得到的路线是:R={(1,2),(2,5),(2,4),(4,6),(1,3)},长度为:1+3+4+3+5=16.如下图
\qquad
其实最小生成树又叫最小支撑树,不同教材或者书籍的叫法不同,比如人民邮电出版社出版的《运筹学导论》中叫“最小生成树”,而科学出版社出版的《运筹学(第三版)》中叫“最小支撑树”。而最小生成树的生成算法也有很多,其中比较常用的是破圈法和避圈法,而上面介绍的算法即避圈法。