第六部分 圖算法
第23章 最小生成樹
一個無環子集T⊆E,既能夠將所有的結點連接起來,又具有最小的權重。由於T是無環的,並且連通所有的結點,因此,T必然是一棵樹。我們稱這樣的樹爲(圖G的)生成樹,因爲它是由圖G所生成的。我們稱求取該生成樹的問題爲最小生成樹問題。
1.最小生成樹的形成
在每遍循環之前,A是某棵最小生成樹的一個子集。在每一步,我們要做的事情是選擇一條邊(u,v),將其加入到集合A中,使得A不違反循環不變式,即A∪{(u,v)}也是某棵最小生成樹的子集。由於我們可以安全地將這種邊加入到集合A而不會破壞A的循環不變式,因此稱這樣的邊爲集合A的安全邊。
Generic-MST(G, w)
A = ∅
while A does not formed a spanning tree
find and edge(u, v) that is safe for A
A = A ∪ {(u,v)}
return A
無向圖G=(V,E)的一個切割(S,V-S)是集合V的一個劃分。
如果一條邊(u,v)∈E的一個端點位於集合S,另一個端點位於集合V-S,則稱該條邊橫跨切割(S,V-S)。
如果集合A中不存在橫跨該切割的邊,則稱該切割尊重集合A。
在橫跨一個切割的所有邊中,權重最小的邊稱爲輕量級邊。
2.Kruskal算法和Prim算法
在Kruskal算法中,集合A是一個森林,其結點就是給定圖的結點。每次加入到集合A中的安全邊永遠是權重最小的連接兩個不同分量的邊。在Prim算法裏,集合A則是一棵樹。每次加入到A中的安全邊永遠是連接A和A之外某個結點的邊中權重最小的邊。
Kruskal算法
MST-Kruskal(G, w)
A = ∅
for each vertex v∈G.V
Make-Set(v)
sort the edges of G.E into nondecreasing order by weight w
for each edge(u,v)∈G.E, taken in nondecreasing order by weight
if Find-Set(v) != Find-Set(u)
A = A ∪ {(u,v)}
Union(u,v)
return A
Kruskal算法的時間代價爲O(ElgV)
Prim算法
MST-Prim(G, w, r)
for each u∈G.V
u.key = ∞
u.π = NIL
r.key = 0
Q = G.V
while Q != ∅
u = Extract-Min(Q)
for each v∈G.Adj[u]
if v∈Q and w(u,v) < v.key
v.π = u
v.key = w(u,v)
Prim算法的時間代價爲O(ElgV)。從漸近意義上來說,它與Kruskal算法的運行時間相同。
如果使用斐波那契堆來實現最小優先隊列Q,則Prim算法的運行時間將改進到O(E+VlgV)。