最小生成樹

2022-09-24 05:39:08 字數 1864 閱讀 3858

目錄給定一張邊帶權的無向圖\(g = (v,e)\),\(n = |v|\),\(m = |e|\)。由\(v\)中n個頂點和\(e\)中n - 1條邊構成的無向聯通子圖稱為\(g\)的一棵生成樹。邊的權值最小之和最小的生成樹稱為\(g\)的最小生成樹

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

kruskal演算法總是維護無向圖的最小生成森林,最初可認為森林由零條邊構成,每個節點各自構成一棵只含乙個點的樹

在任意時刻從剩下的邊中選取權值最小的,並且這條邊的兩個端點屬於森林中不同的兩棵樹,則把該邊加入森林。用並查集維護圖中節點的連通性

演算法流程:

1.建立並查集,每個點各自構成乙個集合

2.把所有邊按照邊權大小從小到大排序,依次掃瞄每條邊(\(x\),\(y\),\(z\))

3.若\(x,y\)屬於同一集合,則忽略這條邊,繼續掃瞄下一條邊

4.若\(x,y\)屬於不同集合,合併\(x,y\)所在的集合,並把邊權\(z\)累加到答案中

5.所有邊掃瞄完畢後,4中掃過的邊就構成最小生成樹

時間複雜度:\(o(m log m)\)

**:

#include using namespace std;

#define maxn 100010

struct node

edge[maxn * 2];//用struct陣列存邊

int f[maxn],n,m,ans;//f為並查集陣列

bool cmp(node a,node b)//按照邊權從小到大排序

int find(int i)//並查集判聯通

int main()

cout << ans << endl;

return 0;

}

prim演算法總是維護最小生成樹的一部分,最初,prim演算法僅確定1號節點屬於最小生成樹。

在任意時刻,設已經確定屬於最小生成樹的點的集合為\(t\),剩餘節點集合為\(s\),prim演算法找到\(min_x\in _s,_y\in_t\),即兩個端點分別屬於集合\(s\),\(t\)的權值最小的邊,然後把點\(x\)從集合\(s\)中刪除,加入到集合\(t\)中,並把\(z\)累加到答案中。

具體地,我們可以維護乙個陣列\(d\):若\(x \in s\),則\(d[x]\)表示節點\(x\)與集合\(t\)中的節點之間邊權最小的邊的權值。若\(x\)屬於\(t\),則\(d[x]\)就等於\(x\)被加入\(t\)的時候選出的最小邊的權值。

可以模擬dijkstra演算法,用乙個陣列標記節點是否屬於\(t\)。每次從未標記的節點中選出\(d\)值最小的,把它標記(加入\(t\)),同時掃瞄出所有邊,更新另乙個端點的\(d\)值。最後,最小生成樹的權值總和就是\(\sum\)

\(n\atop x = 2\)

\(d[x]\).

prim演算法的時間複雜度為\(o(n^2)\),可以用二叉堆優化到\(o(m log n)\),但用二叉堆優化不如直接使用kruskal演算法方便。因此,prim演算法在稠密圖中更優(尤其是完全圖的最小生成樹的求解),kruskal演算法在稀疏圖中更優。

**:

int a[maxn][maxn],d[maxn],n,m,ans;

bool v[maxn];

void prim()

}int main()

prim();//跑最小生成樹

for (int i = 2;i <= n;i++)

ans += d[i];

cout << ans << endl;

}

最小生成樹 次小生成樹

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