最小生成樹

2021-09-29 06:43:41 字數 1915 閱讀 1958

定理:任意一棵最小生成樹一定包含無向圖中權值最小的邊。

證明:假設無向圖g=(v,e)存在一棵最小生成樹不包含權值最小的邊。設e=(x,y,z)是無向圖中權值最小的邊。把e新增到樹中,e會和樹上從x到y的路徑一起構成乙個環,並且環上其它邊的權值都比z大。因此,用e代替環上的其它任意一條邊,會形成一棵權值和更小的生成樹,與假設矛盾。因此假設不成立,原命題成立。

推論:給定一張無向圖g=(v,e),n=|v|,m=|e|。從e中選出k1.kruskal演算法

步驟:first:建立並查集,起初,每個點各自構成乙個集合。

second:把所有的邊按照權值從小到大排序,依次掃瞄每條邊(x,y,z)。

third1:若x,y屬於同一集合,就跳過。

third2:若x,y不屬於同一集合,合併x,y所在的集合,並把z累加到答案中。

last:所有邊掃瞄完成後,third2中處理過的邊就構成最小生成樹。

時間複雜度:o(mlog m)

**:

#include

#include

#include

#include

#define maxn 10005

using

namespace std;

int fa[maxn]

;//父節點

int n,m;

int ans;

//最小生成樹的邊權和

struct nodeedge[maxn]

;bool

operator

<

(node a,node b)

//結構體排序,按照邊的長度從小到大排

intget

(int x)

//並查集

intmain()

printf

("%d"

,ans)

;return0;

}

2.prim演算法

步驟:first :建立兩個集合t,s,t集合裡放已經確定屬於最小生成樹的節點,s集合裡放剩餘的節點,起初t集合裡只有1號節點,剩下的都在s集合中。

second:找到一條分別由t集合裡的點和s集合的點所連成的最短的邊,把這個s集合裡的點放到t集合中,並且在s集合中刪除該點,累計答案。

last:重複second,直至s集合中不存在元素。

時間複雜度o(n²),當然,使用二叉堆優化可以到達o(mlog n),但是過於複雜,正是因為這樣,prim演算法主要運用於稠密圖。

**:

#include

#include

#include

#include

#define maxn 1005

using

namespace std;

int a[maxn]

[maxn]

,dist[maxn]

;//鄰接矩陣存圖

bool vis[maxn]

;int n,m;

int ans;

void

prim()

}int

main()

prim()

;for

(int i=

2;i<=n;i++

) ans+

=dist[i]

;//累加權值

printf

("%d"

,ans)

;return0;

}

上面**中用標記的方法解決了s,t兩個集合的處理問題。

dist陣列作用類似dijstra中使用的dist陣列,但是這裡的dist陣列的作用又有所不同:若節點屬於集合s,則該節點的dist值就是該節點與集合t中的節點之間長度最小的邊的長度。若節點屬於集合t,則該節點的dist值就是該節點被加入t集合時選出的最小邊的長度。

emmm,結束。

最小生成樹 次小生成樹

一 最小生成樹 說到生成樹首先要解釋一下樹,樹是乙個聯通的無向無環圖,多棵樹的集合則被稱為森林。因此,樹具有許多性質 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...