目錄
- 1 最小生成樹問題
- 2 貪心選擇性質(zhì)
2.1 貪心選擇框架——選擇安全邊
2.2 安全邊的辨認(rèn)規(guī)則 - 3 最優(yōu)子結(jié)構(gòu)
- 4 Kruskal算法
- 5 Prim算法
1 最小生成樹問題
2 貪心選擇性質(zhì)
2.1 貪心選擇框架——選擇安全邊
貪心策略:
該算法的理解:
- a.集合A總保持無環(huán)狀態(tài),因?yàn)槭且豢脴洌灰虼藢?duì)于集合A為安全的邊(u, v)所連接的是GA中不同的連通分量;因此,每執(zhí)行一次循環(huán),減少一棵樹
- b.算法執(zhí)行的任意時(shí)刻,圖GA = (V, A)是一個(gè)森林,GA中的每個(gè)連通分量是一棵樹
算法開始時(shí),集合A為空,森林中包含|V|棵樹,每棵樹只有一個(gè)節(jié)點(diǎn); - c.由a, b可知,while循環(huán)總共執(zhí)行|V| - 1次,當(dāng)整個(gè)森林僅包含一棵樹時(shí),終止
循環(huán)不變式:
在每次循環(huán)之前,A是某棵最小生成樹的一個(gè)子集。
安全邊:滿足如下條件的邊稱之為安全邊。
將邊(u, v)加入到集合A中,使得A不違反循環(huán)不變式,即AU{(u, v)}也是某棵最小生成樹的子集。
2.2 安全邊的辨認(rèn)規(guī)則
切割:無向圖G=(V, E)的一個(gè)切割(S, V-S)是集合V的一個(gè)劃分
橫跨:邊(u, v)橫跨切割(S, V-S)表示一個(gè)端點(diǎn)在集合S,一個(gè)在V-S
尊重:如果集合A中不存在橫跨該切割的邊,則稱該切割尊重集合A
輕量級(jí)邊:在橫跨一個(gè)切割的所有邊中,權(quán)重最小的邊稱為輕量級(jí)邊
- 特別注意:之前將切割和尊重誤解了。切割,可以將A分為不相連通的兩部分,而不是將A放到一邊。
貪心策略中辨認(rèn)安全邊的規(guī)則:
一個(gè)推論:
一個(gè)問題:為什么該切割尊重集合A
- 根據(jù)定義:因?yàn)榧螦中不存在橫跨該切割的邊
該切割區(qū)分了C,將集合A分為兩部分,C和A-C,但是C和A-C并不連通。
所以不存在橫跨該切割的一條輕量級(jí)邊。
3 最優(yōu)子結(jié)構(gòu)
如果一個(gè)問題的最優(yōu)解中包含了子問題的最優(yōu)解,則該問題具有最優(yōu)子結(jié)構(gòu)。
最小生成樹是滿足最優(yōu)子結(jié)構(gòu)的,下面會(huì)給出證明:
最優(yōu)子結(jié)構(gòu)描述:假設(shè)我們已經(jīng)得到了一個(gè)圖的最小生成樹(MST) T,(u, v)是這棵樹中的任意一條邊。如圖所示:
現(xiàn)在我們把這條邊移除,就得到了兩棵子樹T1和T2,
如圖:
- T1是圖G1=(V1, E1)的最小生成樹,G1是由T1的頂點(diǎn)導(dǎo)出的圖G的子圖,E1={(x, y)∈E, x, y ∈V1}
同理可得T2是圖G2=(V2, E2)的最小生成樹,G2是由T2的頂點(diǎn)導(dǎo)出的圖G的子圖,E2={(x, y)∈E, x, y ∈V2}
現(xiàn)在我們來證明上述結(jié)論:使用剪貼法。w(T)表示T樹的權(quán)值和。
首先權(quán)值關(guān)系滿足:w(T) = w(u, v)+w(T1)+w(T2)
假設(shè)存在一棵樹T1'比T1更適合圖G1,那么就存在T'={(u,v)}UT1'UT2',那么T'就會(huì)比T更適合圖G,這與T是最優(yōu)解相矛盾。得證。 - 特別注意,上圖中(u, v)這條邊是連接兩棵樹的最小邊(安全邊)
4 Kruskal算法
- 集合A是一個(gè)森林,每次加入到集合A中的安全邊永遠(yuǎn)是權(quán)重最小的連接兩個(gè)不同分量的邊。
- 運(yùn)行時(shí)間分析
集合使用不相交集(并查集)實(shí)現(xiàn),參見基本數(shù)據(jù)結(jié)構(gòu)ADT及其實(shí)現(xiàn)
排序:O(ElgE)
O(E)個(gè)FIND-SET和UNION操作,|V|個(gè)MAKE=SET操作:O((V+E)α(V))
若G是連通的|E| ≥|V| -1,因此總時(shí)間為O(ElgE),|E| < |V|2,則有O(ElgV)。
5 Prim算法——廣度優(yōu)先搜索
- 集合A是一棵樹,每次加入到A中的安全邊永遠(yuǎn)是連接A和A之外某個(gè)節(jié)點(diǎn)的邊中權(quán)重最小的邊。
- 廣度優(yōu)先搜索的思想——當(dāng)從Q中取出一個(gè)點(diǎn)u時(shí),即要檢查u的所有相鄰的點(diǎn),并更新相關(guān)的點(diǎn)。
- Prim算法與分支限界法類似,利用廣度優(yōu)先搜索和優(yōu)先隊(duì)列思想,只不過是沒有使用分支限界思想。因?yàn)榭梢宰C明貪心選擇性質(zhì),使之可以組成一個(gè)最優(yōu)解。
- 該算法的一個(gè)簡(jiǎn)要分析:
初始化:r.key = 0,其余節(jié)點(diǎn)u.key = 無窮大;
第一次循環(huán):將r從Q中剔除,并更新r的所有鄰節(jié)點(diǎn)的key
以此類推;
所有不在樹A中的結(jié)點(diǎn)都存放在一個(gè)基于key屬性的最小優(yōu)先隊(duì)列Q中。對(duì)于每個(gè)結(jié)點(diǎn)v,屬性v.key保存的是連接v和樹中結(jié)點(diǎn)的所有邊中最小邊的權(quán)重。 - 循環(huán)不變式:
1)A = {(v, v.π): v∈V-{r}-Q}
2)已經(jīng)加入到最小生成樹的結(jié)點(diǎn)集合為V-Q
3)對(duì)于所有的結(jié)點(diǎn)v∈Q,如果v.π≠NIL,則v.key < ∞并且v.key是連接結(jié)點(diǎn)v和最小生成樹中某個(gè)結(jié)點(diǎn)的輕量級(jí)邊(v, v.π)的權(quán)重 - 正確性:找出結(jié)點(diǎn)u∈Q,該結(jié)點(diǎn)是某條橫跨切割(V-Q, Q)的輕量級(jí)邊(u.π, u)的一個(gè)端點(diǎn)(第一次循環(huán)除外)。接著將u從隊(duì)列Q中刪除,并將其加入到集合V-Q中,也即將(u.π, u)加入到集合A中。
-
運(yùn)行時(shí)間分析:
1)如果用二叉堆
建堆:O(V)
EXTRACT-MIN:O(VlgV)
判斷結(jié)點(diǎn)是否屬于Q:O(E),利用一個(gè)標(biāo)志位來指明結(jié)點(diǎn)是否屬于Q(O(1)即可判斷)
DECREASE-KEY:O(ElgV)
總時(shí)間為O(ElgV)
2)如果用斐波那契堆
DECREASE-KEY:O(E)
總時(shí)間為O(E+VlgV)