算法設計與分析課程複習筆記10——最小生成樹
最小生成樹MST
修路問題
一個小鎮有一些房子和一些路,每條路連接且僅連接2座房子,連接u和v房子的路的維修代價爲w(u,v),
現在要維修僅夠需求的道路,使得:每兩座房子之間保持連通,維修代價最小。
圖爲連通無向圖,頂點爲房子,邊爲路,維修費用爲邊的權。
找到一個T,T爲E的子集,並且w(T)=
最小生成樹特性
- 非唯一
- 沒有迴路
- MST邊的數目爲頂點數目減1
MST生成
一般方法:
創建一個邊的集合A,起始時爲空
逐漸向A中添加邊並保持A屬於某個MST
當且僅當A ∪ {(u, v)}是MST的子集,我們說邊(u, v)對於A是安全的
MST一般算法
A ← 空集
while A is not a spanning tree(沒有形成生成樹)
do find an edge(u,v) that is safe for A(尋找對A安全的邊(u, v))
A ← A ∪ {(u,v)}
return A
如何找到對A安全的邊?
一些定義:
- 切割:將圖的頂點分成兩個互不相連的兩個集合S和V – S
- 如果一個邊的兩個端點分別在切割的兩個集合S和V - S中,我們說該邊橫跨該切割
- 一個切割不干預集合A 集合A中沒有邊與該切割相交
- 橫跨切割的輕邊 所有橫跨切割的邊中權值最小的邊
定理:
A是MST的子集, (S, V - S)是不干預A的一個切割, (u, v)是橫跨該切割的輕邊,那麼, (u, v)對於A是安全的。
Kruskal算法
- 從每個頂點開始,每個頂點即是個組件
- 通過選擇輕邊LE,不斷的將兩個組件連接起來
- 依權值遞增順序檢查邊的集合
- 利用不相關集合的數據結構判斷邊是否連接不同的組件
不相關集合的操作
- MAKE-SET(u)創建集合,僅含元素u
- FIND-SET(u)包含u,返回代表元素
- 集合的任何元素具有某個特定的屬性
- 集合的特性是按字母順序的第一個字母
E.g.: = {r, s, t, u},FIND-SET(u) = r,FIND-SET(s) = r - 對於給定的集合,返回同樣的值
- UNION(u,v)合併操作
E.g.: = {r, s, t, u}, = {v, x, y}
UNION (u, v) = {r, s, t, u, v, x, y}
Kruskal(V,E,w)
A ← 空集
for each vertex v ∈ V
do MAKE-SET(v)
sort E into non-decreasing order by weight w(權值遞增排序)
for each (u, v) taken from the sorted list
do if FIND-SET(u) ≠ FIND-SET(v) (屬於不同的組件)
then A ← A ∪ {(u, v)}
UNION(u, v)
return A
運行開銷:
Prim算法
- 集合A中的邊形成一棵樹
- 從任意選定的根開始
- 每次
- 確定切割(, V - )的LE
- 將LE加入A
- 重複直到樹包含所有頂點
- 貪婪策略:每次加入的邊使樹的邊的權值和增加最小
如何快速確定LE?
利用優先隊列
- 包含所有不在樹中的頂點(V – )
- 每個頂點賦予一個關鍵值,即樹中連接至v的任何邊(u, v)的最小權值
如果v與任何的頂點不相連,則關鍵值爲
增加節點後,所有與之相連的節點的關鍵值要做調整
Prim(V,E,w,r)
Q ← 空集
for each u ∈ V
do key[u] ←
π[u] ← NIL
key[r] ←0
Q ← V
while Q ≠ 空集
do u ← EXTRACT-MIN(Q)
for each v ∈ Adj[u]
do if v ∈ Q and w(u, v) < key[v]
then π[v] ← u
key[v] ← w(u, v)
算法分析
參考:任課教師邱德紅教授的課件