一、最小生成樹簡介
假設有乙個很實際的問題:我們要在n個城市中建立乙個通訊網路,則連通這n個城市需要布置n-1一條通訊線路,這個時候我們需要考慮如何在成本最低的情況下建立這個通訊網?
於是我們就可以引入連通圖來解決我們遇到的問題,n個城市就是圖上的n個頂點,然後,邊表示兩個城市的通訊線路,每條邊上的權重就是我們搭建這條線路所需要的成本,所以現在我們有n個頂點的連通網可以建立不同的生成樹,每一顆生成樹都可以作為乙個通訊網,當我們構造這個連通網所花的成本最小時,搭建該連通網的生成樹,就稱為最小生成樹。
圖的生成樹是它的一顆含有其所有頂點的無環連通子圖,一幅加權圖的最小生成樹(mst)是它的一顆權值(樹中的所有邊的權值之和)最小的生成樹。下圖為一幅加權無向圖和它的最小生成樹.(箭頭不指示方向,標紅的為最小生成樹):
最小生成樹可以使用克魯斯卡爾演算法和普里姆演算法實現。
二、克魯斯卡爾演算法
1、演算法思路
1. 將圖中的所有邊都去掉;
2. 將邊按權值從小到大的順序新增到圖中,保證新增的過程中不會形成環 ;
3. 重複上一步直到連線所有頂點,此時就生成了最小生成樹。這是一種貪心策略。
2、**克魯斯卡爾演算法
(1)如何判斷環:使用乙個multiset儲存所有邊的資訊,如果起點和終點都在st1中則加入該邊會形成環。
3、克魯斯卡爾演算法的demo:
#include
using
namespace
std;
struct edge//紀錄邊的資訊
;//克魯斯卡爾演算法
void kruskal(int data[10][3])
; multiset
st1;
vector
vec;//儲存所有邊的資訊
edge temp;
for (int j = 0; j < 10; ++j)//初始化所有邊的資訊
//按權值排序
sort(vec.begin(), vec.end(), (const edge &e1, const edge &e2) -> bool
);for (int j = 0; j < 10; ++j)
}for (int j = 0; j < 10; ++j)
}int main(int argc, char
const *argv)
,, ,,
,,,,,};
kruskal(data);
return
0;}
三、普里姆演算法1、演算法思路對於圖g而言,v是所有頂點的集合;現在,設定兩個新的集合u和t,其中u用於存放g的最小生成樹中的頂點,t存放g的最小生成樹中的邊。 從所有uєu,vє(v-u) (v-u表示出去u的所有頂點)的邊中選取權值最小的邊(u, v),將頂點v加入集合u中,將邊(u, v)加入集合t中,如此不斷重複,直到u=v為止,最小生成樹構造完畢,這時集合t中包含了最小生成樹中的所有邊。
2、**普里姆演算法
(1)複雜度分析:克魯斯卡爾演算法的時間複雜度為o(eloge);普里姆演算法的時間複雜度為,鄰接矩陣:o(v^2),鄰接表:o(elog2v)。
(2)克魯斯卡爾演算法主要針對邊展開,邊數少時效率會很高,所以對於稀疏圖有優勢而普利姆演算法對於稠密圖,即邊數非常多的情況會好些。
最小生成樹之克魯斯卡爾演算法
include iostream include algorithm using namespace std struct edge 用於把所有邊按權重的大小排序 bool comp const edge e1,const edge e2 使用並查集來判斷兩個點是否在同乙個連通塊中。在每個連通塊中,...
最小生成樹 克魯斯卡爾演算法
c node.h檔案 儲存頂點資訊 class c node c node c node c node p node c node c node c node c node char p data node.h檔案,儲存邊資訊 include class link node link node li...
最小生成樹( 克魯斯卡爾演算法)
name author date 01 12 14 20 17 description 最小生成樹 克魯斯卡爾演算法 關於並查集的演算法,參見 一種簡單而有趣的資料結構 並查集 include include define maxn 1000 最大頂點數量 define max 20000 最大邊數...