1. 程式人生 > >圖之最小生成樹 Kruskal演算法 Prim演算法

圖之最小生成樹 Kruskal演算法 Prim演算法

一.實際問題

最小生成樹一般應用在網(帶權的圖)問題中,實際問題一般比如:
  假設要在n個城市間建立通訊聯絡網,則聯通n個城市只需要n-1條線路,但是每兩個城市間都可以建設路線,而且城市與城市間建設代價是不同的,這就需要我們考慮一種經濟的聯絡方式。
將問題轉換成圖的話,就如下圖(圓圈代表城市,線代表線路,線上數值代表建設的代價),我們需要從中選擇一條代價最小的建設方式。
這裡寫圖片描述

二.基本思想

  一般情況下這類問題歸於動態規劃中的貪心演算法(不一定是但大多數情況下是最優解)。
  這裡寫圖片描述
  跟動態規劃一樣,我們假設上圖弧線以下部分(白色圓圈c,i,h,g,f部分)已經找到最優解的話,那麼我們考慮新增一個黑色圓圈時,只需要考慮白色圓圈c,i,h,g,f部分到黑色園圈所有線路中代價最小的線路與黑色園圈相連組成新的子問題最優解(比如白色圓圈c,i,h,g,f部分到最左邊黑色圓圈有代價8或11線路,顯然我們選擇線路代價為8)。接下來介紹的Kruskal和Prim演算法其基本思想大抵如此。

三.Kruskal演算法

適合求解邊稀疏網的最小生成樹

克魯斯卡爾演算法首先把每一個節點當成一最小生成棵樹,把所有的邊從代價小到大排列。
然後逐個選擇邊(從小到大):
  判斷邊是否連線兩個最小生成樹,如果能夠連線則把兩棵最小生成樹連線起來生成一個最小生成樹;   如果這條邊連線的是一棵樹內兩個節點的話就拋棄它,為什麼呢?因為我們是從小到大選擇的邊,如果把當前這條邊加入這棵樹的話,樹內必定會生成一個迴路,就需要拋棄一條邊,然而先前選擇的所有的邊都比當前這條邊代價小,所以只能拋棄當前這條邊。
  這裡寫圖片描述
看上述示意圖中,紅圈部分就是代價高的線路被拋棄了。
演算法例項:CCF 地鐵修建

四.Prim演算法

適合求解邊稠密網的最小生成樹

普西姆演算法與克魯斯卡爾演算法不同,普西姆演算法從始到終都只有一棵樹。
首先選擇任意一個頂點當成一棵樹,把(樹)和(其他節點)當成兩個集合;
然後我們從(其他節點)到(樹)線路中選擇代價最小的線路,這條線路的端節點必然一個在(樹)中,一個在(其他節點)中。把該條最小代價線路在(其他節點)集合中的節點轉移到(樹)中,從而形成新的最小生成樹。重複上述步驟,到最後所有的節點都在(樹)集合中。
這裡寫圖片描述
看上述示意圖中,始終只有黑色圓圈組成的(樹),在只有一個黑點(圖1)時,(樹)與(其他集合)有兩條線路,代價分別為4或8,顯然選擇4;
然後(樹)與(其他集合)間線路就有8或11或8,按貪心演算法,我們只需考慮一個子問題,所以選擇其中一條代價為8的線路即可。

CCF 最優灌溉
演算法例項:CCF 交通規劃