Prim算法和Kruskal算法的正確性證明


今天學習了Prim算法和Kruskal算法,因為書中只給出了算法的實現,而沒有給出關於算法正確性的證明,所以嘗試着給出了自己的證明。剛才看了一下《算法》一書中的相關章節,使用了切分定理來證明這兩個算法的正確性,更加簡潔、優雅並且根本。相比之下,我的證明帶着許多草莽氣息,於此寫成博客,只當是記錄自己的思考
 
-------------------------------------------
 
說明:
本文僅提供關於兩個算法的正確性的證明,不涉及對算法的過程描述和實現細節
本人算法菜鳥一枚,提供的證明僅是自己的思路,不保證正確,僅供參考,若有錯誤,歡迎拍磚指正
關於使用切分定理來證明兩個算法的正確性,請參考《算法》一書中的相關章節
 
-------------------------------------------

Prim算法和Kruskal算法用來求解無向連通圖中的最小生成樹,相關概念這里不作介紹
 
Prim算法的思路是,從任意一個頂點開始,把這個頂點作為最初的最小生成樹的子樹,通過逐步地為當前的子樹添加新邊來生成最終的最小生成樹,添加的策略是,每次只添加從外部連接到該子樹的所有邊中的最短邊
 
這種算法之所以可行,是基於這樣一個判斷:對於任意一個頂點vi,連接到該頂點的所有邊中的一條最短邊(vi, vj)必然屬於最小生成樹(該判斷也可以擴展成:任意一個屬於最小生成樹的連通子圖(子樹),從外部連接到該連通子圖的所有邊中的一條最短邊必然屬於最小生成樹
 
下面證明如上的判斷:
假設最小生成樹已經建成;(vi, vj)是連接到頂點vi的最短邊,在最小生成樹中取出vi,斷開連接到vi的邊,則生成樹被拆分成
1、頂點vi
2、頂點vj所在的連通分量(單獨一個頂點也看作一個獨立的連通分量)
3、其余若干個連通分量(個數大於等於0)
三個部分
 
現在要重建生成樹,就要重新連接之前被斷開的各邊
雖然不知道之前被斷開的都是哪幾條邊,但是可以通過這樣一個簡單的策略來重建連接:將vi分別以最小的成本逐個連接到這若干個互相分離的連通分量;具體來說,就是要分別遍歷頂點vi到某個連通分量中的所有頂點的連接,然后選擇其中最短的邊來連接vi和該連通分量;而要將vi連接到vj所在的連通分量,顯然通過邊(vi, vj)連接的成本最低,所以邊(vi, vj)必然屬於最小生成樹(如果連接到vi的最短邊不止一條,只要任意挑選其中的一條(vi, vj)即可,以上的證明對於這種情況同樣適用)
 
這樣我們就為原來只有一個頂點vi的子樹添加了一個新的頂點vj及新邊(vi, vj);接下來只要將這棵新子樹作為一個連通子圖,並且用這個連通子圖替換頂點vi重復以上的分析,迭代地為子樹逐個地添加新頂點和新邊即可
 
--------------------------------------------- 
 
Kruskal算法通過從小到大遍歷邊集,每次嘗試為最小生成樹加入當前最短的邊,加入成功的條件是該邊不會在當前已構建的圖中造成回路,當加入的邊的數目達到n-1,遍歷結束
 
Kruskal算法每次為當前的圖添加一條不會造成回路的新邊,其本質是逐步地連接當前彼此分散的各個連通分量(單個頂點也算作一個連通分量),而連接的策略是每次只用最小的成本連接任意兩個連通分量。這個策略之所以能夠實現,是因為每加入一條邊之后只會出現兩種結果:
1、在已有的連通分量中形成回路
2、連接兩個彼此獨立的連通分量
所以,通過從小到大遍歷邊集,判斷是否會造成回路,然后逐條添加新邊就可以實現上訴的連接策略
 
接下來需要證明的是,為什么每次用最小成本連接兩個連通分量,最后就可以生成一棵最小生成樹(畢竟每一個當前的最優解之和未必是全局的最優解)
 
借用在Prim算法中提到的那個判斷就可以很方便地證明:“如果某個連通圖屬於最小生成樹,那么所有從外部連接到該連通圖的邊中的一條最短的邊必然屬於最小生成樹”
通過這個判斷,可以很容易地證明:當最小生成樹被拆分成彼此獨立的若干個連通分量的時候,所有能夠連接任意兩個連通分量的邊中的一條最短邊必然屬於最小生成樹(因為該邊必然是這兩個連通分量的可以連接到外部的最短邊)
 
由此也就證明了,Kruskal算法通過每次以最小的成本來連接兩個連通分量的策略確實可以正確地生成最小生成樹
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM