Kruskal最小生成樹及應用

2022-05-19 18:53:05 字數 2446 閱讀 9121

生成樹:

已知連通圖g,圖上有n個頂點。

生成樹是指圖g的乙個極小(邊最少)連通子圖,生成樹上有n個頂點,n-1條邊,且任意兩點之間都是聯通的。

最小生成樹:

已知帶權連通圖g,圖中有n個頂點,每條邊都有權值。

要從圖中抽出一棵生成樹,使得樹上所有邊權之和最小,這棵樹就叫做最小生成樹(mininum spanning tree,mst)。

常見解法有kruskal演算法和prim演算法。

kruskal演算法:

定義帶權無向圖g的邊集合為e,再定義最小生成樹的邊集合為t,初始集合t=空。

1.首先把圖g看成乙個有n棵樹的森林,圖上每個頂點對應一棵樹;

2.然後把邊集e的每條邊,按照權值從小到大進行排序;

3.按邊權從小到大的順序遍歷每條邊e=(u,v),我們記頂點u所在的樹為tu,頂點v所在的樹為tv,如果tu和tv不是同一棵樹,則我們將邊e加入集合t,並將兩棵樹tu和tv進行合併;否則不進行任何操作。

演算法執行完畢後,如果集合t包含n-1條邊,則t就代表最小生成樹中的所有邊。

第三步操作需要對集合進行合併操作,因此要用並查集來維護。

演算法複雜度:若使用快排則複雜度為o(eloge),總時間複雜度為o(eloge+vα(v)),其中α(v)可近似被當作常數。

帶詳細解釋の模板:

#include #include 

#include

#include

using

namespace

std;

const

int max_n = 100000; //

最大頂點數

const

int max_m = 100000; //

最大邊數

struct

edge e[max_m];

int fa[max_n], n, m; //

fa 陣列記錄了並查集中結點的父親

bool

cmp(edge a,edge b)

//並查集相關**

int ancestor(int x)

int same(int x, int y)

void merge(int x, int y)

intmain()

sort(e + 1, e + m + 1, cmp); //

對邊按邊權進行公升序排序

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

int rst = n, ans = 0; //

rst 表示還剩多少個集合,ans 儲存最小生成樹上的總邊權

for (int i = 1; i <= m && rst > 1; i++) else

}printf(

"%d\n

", ans);

return0;

}

view code

自用模板:

#includeusing

namespace

std;

const

int maxn=1e5+10;//

最大頂點數

const

int maxm=1e5+10;//

最大邊數

struct

edge

e[maxm];

intfa[maxn],n,m;

bool

cmp(edge a,edge b)

intget(int

x)int

main()

}printf(

"%d\n

",ans);

return0;

}

最小生成樹的應用:

例一:最大邊權最小的生成樹

給定乙個無向連通圖,求出它所有生成樹中最大邊權最小的一棵。

解法:可二分,列舉生成樹的邊權上界之後判定是否存在邊權不超過限制的生成樹。

正解為直接求最小生成樹,因為最小生成樹中的最大邊一定是所有生成樹中最小的(聯絡最小生成樹的生成原理)。

例二:次小生成樹

給定乙個無向連通圖,求出它的邊權總和第二小的生成樹。

解法:列舉最小生成樹上的n條邊,對於其中某條邊,從圖中刪除它以後計算剩餘圖的最小生成樹,一共n-1棵。從這n-1棵生成樹中找出最小的一顆,就是整個圖的次小生成樹。

例三:邊權極差最小生成樹

給定乙個無向連通圖,求它所有生成樹中,最大邊權和最小邊權之差最小的生成樹。

解法:利用例題一中給出的性質,列舉生成樹上的最小邊權minw,計算邊權最小為minw的最小生成樹,用當前最小生成樹的最大邊減去最小邊來更新最終答案。

kruskal 最小生成樹

include include 產生隨機數組用 include 同上 include using namespace std 1 帶權邊的類myarc class myarc bool operator const myarc arc myarc myarc int beginvex,int end...

最小生成樹Kruskal

最小生成樹有兩個特點,乙個是保證了所有邊的和是最小值,另乙個是保證了所有邊中的最大值最小。struct edge bool friend operator edge a,edge b 構邊 vectoredge int id max int mini void initial void input ...

最小生成樹(kruskal)

kruskal演算法 1 記graph中有v個頂點,e個邊 2 新建圖graphnew,graphnew中擁有原圖中相同的e個頂點,但沒有邊 3 將原圖graph中所有e個邊按權值從小到大排序 4 迴圈 從權值最小的邊開始遍歷每條邊 直至圖graph中所有的節點都在同乙個連通分量中 if 這條邊連線...