最小生成樹(Kruskal Prim) 模板

2022-05-03 14:12:20 字數 2197 閱讀 4644

1、假設以下情景,有一塊木板,板上釘上了一些釘子,這些釘子可以由一些細繩連線起來。假設每個釘子可以通過一根或者多根細繩連線起來,那麼一定存在這樣的情況,

即用最少的細繩把所有釘子連線起來。

2、更為實際的情景是這樣的情況,在某地分布著n個村莊,現在需要在n個村莊之間修路,每個村莊之前的距離不同,問怎麼修最短的路,將各個村莊連線起來。

以上這些問題都可以歸納為最小生成樹問題,用正式的表述方法描述為:給定乙個無方向的帶權圖g=(v, e),最小生成樹為集合t,t是以最小代價連線v中所有頂點所用邊e的最小集合。 集合t中的邊能夠形成一顆樹,這是因為每個節點(除了根節點)都能向上找到它的乙個父節點。

先對所有邊進行排序,以權值最小的邊所在的點為根節點開始處理,用乙個for循遍歷所有排序後的邊,若這條邊的兩個點的根節點不同,累加上權值,再把這兩個點合併,一直處理到最後即可

需要用到並查集知識(並查集的加邊操作記得用路徑壓縮,避免超時),和結構體的排序

int p[100005],r[100005

];int

n,ans;

struct

node

a[100005

];bool

cmp(node b,node c)

int find(int x)//

查詢元素x的老闆是誰

void join(int x, int y)//

路徑壓縮合併兩個集合

}void

kruskal()

}}

由頂點開始(可以隨便找乙個為頂點)形成乙個點集,每次從剩餘點中找乙個與這個點集最近的點(權值最小的點)並加入點集,直到結束

以下流程圖**自謝謝博主^-^

知道了普利姆演算法的核心步驟,下面我就用圖示法來演示一下工作流程,如圖:

首先,確定起始頂點。我以頂點a作為起始點。根據查詢法則,與點a相鄰的點有點b和點h,比較ab與ah,我們選擇點b,如下圖。並將點b加入到u中。

繼續下一步,此時集合u中有兩個點,再分別以這兩點為起始點,根據查詢法則,找到邊bc(當有多條邊權值相等時,可選任意一條),如下圖。並將點c加入到u中。

繼續,此時集合u中有三個點,根據查詢法則,我們找到了符合要求的邊ci,如下圖。並將點i加入到u中。

繼續,此時集合u中有四個點,根絕查詢法則,找到符合要求的邊cf,如下圖。並將點f加入到集合u中。

繼續,依照查詢法則我們找到邊fg,如下圖。並將點g加入到u中。

繼續,依照查詢法則我們找到邊gh,如下圖。並將點h加入到u中。

繼續,依照查詢法則我們找到邊cd,如下圖。並將點d加入到u中。

繼續,依照查詢法則我們找到邊de,如下圖。並將點e加入到u中。

此時,滿足u = v,即找到了這顆最小生成樹。

void

prim()

}vis[k]=1

; ans=ans+mn;

for(int j=1;j<=n;j++)//

更新最小值,k和起點都在處理過的集合裡面,更新到起點的最小值

}}

模板題:hdu1233 還是暢通工程

最小生成樹 次小生成樹

一 最小生成樹 說到生成樹首先要解釋一下樹,樹是乙個聯通的無向無環圖,多棵樹的集合則被稱為森林。因此,樹具有許多性質 1.兩點之間的路徑是唯一的。2.邊數等於點數減一。3.連線任意兩點都會生成乙個環。對於乙個無向聯通圖g的子圖,如果它包含g的所有點,則它被稱為g的生成樹,而各邊權和最小的生成樹則被稱...

最小生成樹

package 圖 最小生成樹是用最少的邊吧把所有的節點連線起來。於是和圖的深度優先搜素差不多。class stack public void push int key public int pop 檢視棧頂的元素 public int peek public boolean isempty cla...

最小生成樹

define max vertex num 20 最大頂點數 typedef int adjmatrix max vertex num max vertex num 鄰接矩陣型別 typedef char vertextype typedef struct mgraph struct dnodecl...