生成樹:
已知連通圖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 #includeview code#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;
}
自用模板:
#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 這條邊連線...