PRIM


最小生成樹Prim

 

最小生成樹的定義

一個有 n 個結點的連通圖的生成樹是原圖的極小連通子圖,且包含原圖中的所有 n 個結點,並且有保持圖連通的最少的邊(度娘原話)

簡單來說,就是一個連接所有點路徑和最小

Prim的思路

設圖的頂點集合為U,樹的頂點集合為V

從圖中任意一點出發,找到N-1條邊(x,y),x∈U,y∈V,且權值最小。

通俗的講,就是不斷找權值最小不產生閉環N-1條邊

栗子

廢話不多說,先上圖

如下圖所示

 

 

 

 

(1)從V3出發

(2)找到邊(V3,V1),符合條件且最小,將V1加入V

以此類推……

(N)找到邊(V2,V5),符合條件且最小,將V5加入V,最小生成樹構造完成

 代碼(C++)

雖然是P黨,但考慮到Pascal受眾較小,我采用C++

代碼巨丑,bug一堆,歡迎巨佬吐槽

務必記住,要將A的初值定為正無窮,不然會卡BUG

/*Prim核心代碼 HYDcn原創*/
for (int i=2;i<=n;i++) { lowcost[i]=a[i][1];//將與V1(或任意一點)有關的邊存入lowcost(與各點最小權值)
 } for (int i=1;i<n;i++) { minval=1000000;//初始化最小值為正無窮
        for (int j=1;j<=n;j++) { if (lowcost[j]>0&&lowcost[j]<minval)//如果當前權值不為0(即未連接過)且更小
 { k=j;//記錄當前點
                    minval=lowcost[j];//將最小值存入
 } } ans+=minval;//統計最小生成樹最小權值和
        lowcost[k]=0;//標記該點
        for (int j=1;j<=n;j++) { if (lowcost[j]>0&&lowcost[j]>a[k][j])//由於U集合點增加,需更新與各點最小權值邊
 { lowcost[j]=a[k][j]; } } } 

輸入

7 9
1 2 28
1 6 10
2 3 16
2 7 14
3 4 12
4 5 22
4 7 18
5 6 25
5 7 24

輸出

99(即權值和)

算法對比

PrimKruskal都是最小生成樹算法

據說Prim算法適用於稠密圖 Kruskal適用於稀疏圖

不知道你們信不信,反正我是不信,因為我被親身卡過

(QAQ算法歧視)

Prim:O(N^2)

Kruskal:O(M log M)

Kruskal在絕大部分情況下不會卡,而Prim很容易被卡

能用Kruskal還是盡量用吧

 


免責聲明!

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



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