第二十三章 最小生成樹
總結:這一章介紹了最小生成樹,並介紹了找出最小生成樹的兩個算法,Prim算法和Kruskal算法,它們都用到了貪心策略。
1. 最小生成樹
對無向連通圖G=(V,E),對圖中的每一條邊(u,v)єE,都有一個權值w(u,v)。我們希望找出一個無迴路的子集T包含於E,它連接了所有的頂點,且其權值之和w(T)=Σw(u,v)爲最小。把確定T的問題稱爲最小生成樹問題。
2. Kruskal算法
用了並查集和貪心策略的思路。初始時,所有結點各自爲一個集合。先從衆多邊中,找出權值最小的那條邊(u,v),如果這條邊屬於同一個集合,則說明u,v已經聯結在一起了,就不用添加了,否則,就是用最小的代價將兩個結點所屬的集合合併,這樣一直下去即可。
運行時間:O(ElgV)
僞代碼
Kruskal(G,w)
A <- 空集
for each vertex vєV[G]
do MAKE-SET(v)
sort the edges of E into nondecreasing order by weight w
for each edge(u,v) є E, taken in nondecreasing order by weight
do if FIND-SET(u)!=FIND-SET(v)
then A <- A U {(u,v)}
UNION(u,v)
return A
3. Prim算法
先選一個點,找出與該點鄰接的所有邊中最小的那一條,然後將新的結點添加進去,再找與新的集合中那些點相鄰接的所有邊中最小的那一條,添加進去,這樣依次下去,形成一顆最小生成樹。
在算法的執行過程中,不在樹中的所有頂點都放在一個基於key域的最小優先級隊列Q中。對每個頂點v,key[v]是所有將v與樹中某一頂點相連的邊中的最小權值;若不存在這樣的邊,則key[v]=無窮大。
運行時間:O(V*EXTRACT-MIN()+E*DECREASE-KEY())
使用二叉最小堆: O(VlgV+ElgV)=O(ElgV)
使用斐波那契堆: O(VlgV+E)
僞代碼
MST-PRIM(G,w,r) //r爲選擇的最初的頂點
for each uєV[G]
do key[u] <- 無窮大
pi[u] <- NIL //pi[u]指在最小生成樹中u的父親結點
key[r] <- 0
Q <- V[G]
while Q!=空
do u <- EXTRACT-MIN(Q)
for each vєAdj[u]
do if vєQ and w(u,v) < key[v]
then pi[v] <- u
key[v] <- w(u,v)