從一個Graph G(V,E)中,分離出一棵包含圖中所有點的樹,
該樹稱為Spanning Tree (生成樹):
(1) T⊆E,連接G裡面所有的vertex。
(2) T是tree,所以不會有cycle。(T是E的acyclic subset)
(3) T剛好有n-1條edges。
生成樹的權重(weight)為樹中每條邊的權重總和,
而權重總和最小的生成樹,
即為最小生成樹。(Minimum Spanning Tree,MST)
首先介紹一個求最小生成樹的一般演算法,
而之後要介紹的Kruskal和Prim演算法,
都是由這個一般演算法的概念衍伸而來,
兩者都是greedy algorithm。
A是一個edges的集合,
每次loop都會加一條edge到A,
而A必須一直維持是MST的subset。
該edge稱為safe edge,代表不會破壞A是MST的edge。
【Kurskal's Algorithm】
1. 一開始圖上每個點各自是一棵MST
2. 圖上的所有邊,依照權重由小到大排序
3. 依序嘗試將每條邊(u,v),加入最終MST的邊 (最終MST會長成forest)
(1) 若該條邊的兩端點(u,v)位在同一棵MST,就會產生cycle,
因此捨棄它,不加入最終的MST。
(2) 若(u,v)分別位在不同的MST,則用該條邊做為橋樑,
連接兩棵MST,該邊即為最終MST之中的一條邊。
Introduction to Algorithms Fig. 23.4 Part1 |
(a)
從weight最小的邊開始,
加入最終MST。
(b)~(e)
weight由小到大,
依序加入最終MST。
(f)
因為(i,g)位在同一棵MST,
會造成cycle,所以捨棄它。
剩下依此類推,
最後搜索完每條邊之後,
圖(n)即為最終MST結果。
Introduction to Algorithms Fig. 23.4 Part2 |
【Prim's Algorithm】
用一個Min-Priority Queue Q,
去儲存所有尚未被加到最終MST裡的vertex。
每個vertex v有一個屬性key,
v.key記錄v到MST中最短的邊的weight,
而Q就是依照key值來排序。
v.π代表MST中v的parent,
也就是最短邊的另外一端的vertex。
演算法實作看起來有點複雜,
但核心觀念就是每次都會去找距離「整棵樹」最近的點,
然後把它加入MST中。
換句話說,與樹相鄰的每條邊中,找weight最低的edge,
並把那條edge加入MST裡。
但要注意準備要加入的那個點不能在目前的MST中,否則會產生cycle。
Introduction to Algorithms Fig. 23.5 |
(a)
首先選一個點當作root,
此點已經是一棵MST,
而與樹相鄰的邊有:
(a,b)、(a,h);
其中(a,b)的權重最小,
因此把(a,b)加入MST中。
(d)
與樹相鄰的邊有:
(a,h)、(i,h)、(i,g)、(c,d)、(c,f);
其中(c,f)的權重最小,
因此把(c,f)加入MST中。
剩下的依此類推,
最後當MST中的edges數量為
n-1條時就完成了,
圖(i)為最終MST的結果。
沒有留言:
張貼留言