[貪心經典算法]Kruskal算法


Kruskal算法的高效實現需要一種稱作並查集的結構。我們在這里不介紹並查集,只介紹Kruskal算法的基本思想和證明,實現留在以后討論。

Kruskal算法的過程:

(1) 將全部邊按照權值由小到大排序。
(2) 按順序(邊權由小到大的順序)考慮每條邊,只要這條邊和我們已經選擇的邊不構成圈,就保留這條邊,否則放棄這條邊。

算法 成功選擇(n-1)條邊后,形成一棵最小生成樹,當然如果算法無法選擇出(n-1)條邊,則說明原圖不連通。
以下圖為例:
邊排序后為:
 
1 AF 1
2 DE 4
3 BD 5
4 BC 6
5 CD 10
6 BF 11
7 DF 14
8 AE 16
9 AB 17
10 EF 33

 

算法處理過程如下:
處理邊AF,點A與點F不在同一個集合里,選中AF。
處理邊DE,點D與點E不在同一個集合里,選中DE
處理邊BD,點B與點D不在同一個集合里,選中BD
處理邊BC,點B與點C不在同一個集合里,選中BC

處理邊CD,點C與點D在同一個集合里,放棄CD。

處理邊BF,點B與點F不在同一個集合里,選中BF。
 
至此,所有的點都連在了一起,剩下的邊DF,AE,AB,EF不用繼續處理了,算法執行結束。
Kruskal算法的證明。假設圖連通,我們證明Krusal算法得到一棵最小生成樹。我們假設Kruskal算法得到的樹是K (注意我們已經假設Kruskal算法一定可以得到生成樹)。假設T是一棵最小生成樹,並且K ≠T, K中顯然至少有一條邊。我們找到在K中,而不在T中最小權值的邊e。

把e加入T中,則形成一個圈,刪掉這個圈中不在K中的邊f,得到新的生成樹T’。
f的存在性,如果全里面所有的邊都在K中,則K包含圈,矛盾。

考慮邊權值關系:

(1) 若w(f) > w(e), 則T’的權值和小於T的權值和,與T是最小生成樹矛盾。
(2) 若w(f) < w(e), 說明Kruskal算法在考慮加入e之前先考慮了邊f,之所以沒加入f是因為f和之前加入的邊形成圈,之前加入的邊權值顯然不超過w(f) (因為加邊是從小到大的順序加入的),所以之前加入的邊權值一定小於w(e)。而根據e的定義,K中權值小於w(e)的邊都在T中,這說明T中的邊會和f構成圈,矛盾。

所以只能w(f) = w(e)。T’仍然是最小生成樹,而T’和K相同的邊多了一條。
這樣下去有限步之后,最終可以把T變為K,從而K也是最小生成樹。
 
N個點M條邊的無向連通圖,每條邊有一個權值,求該圖的最小生成樹。
最后,我們來提供輸入輸出數據,由你來寫一段程序,實現這個算法,只有寫出了正確的程序,才能繼續后面的課程。
 
輸入

第1行:2個數N,M中間用空格分隔,N為點的數量,M為邊的數量。(2 <= N <= 1000, 1 <= M <= 50000)
第2 - M + 1行:每行3個數S E W,分別表示M條邊的2個頂點及權值。(1 <= S, E <= N,1 <= W <= 10000)
輸出
 
輸出最小生成樹的所有邊的權值之和。
 
輸入示例

9 14
1 2 4
2 3 8
3 4 7
4 5 9
5 6 10
6 7 2
7 8 1
8 9 7
2 8 11
3 9 2
7 9 6
3 6 4
4 6 14
1 8 8

輸出示例

37


免責聲明!

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



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