貪心 最小生成樹Kruskal演算法

2021-09-27 15:45:15 字數 1456 閱讀 4793

構造最小生成樹還有一種演算法,kurskal演算法:設g=(v,e)是無向連通帶權圖,v=;設最小生成樹t=(v,te),該樹的初始狀態為只有n個頂點而無邊的非連通圖t=(v,{}),kruskal演算法將這n個頂點看成是n個孤立的連通分支。它首先將所有的邊按權值從小到大排序,然後只要t中選中的邊數不到n−1,就做如下的貪心選擇:在邊集e中選取權值最小的邊(i,j),如果將邊(i,j)加入集合te中不產生迴路(圈),則將邊(i,j)加入邊集te中,即用邊(i,j)將這兩個連通分支合併連線成乙個連通分支;否則繼續選擇下一條最短邊。把邊(i,j)從集合e中刪去。繼續上面的貪心選擇,直到t中所有頂點都在同乙個連通分支上為止。此時,選取到的n−1條邊恰好構成g的一棵最小生成樹t。

那麼,怎樣判斷加入某條邊後圖t會不會出現迴路呢?

該演算法對於手工計算十分方便,因為用肉眼可以很容易看到挑選哪些邊能夠避免構成迴路(避圈法),但使用電腦程式來實現時,還需要一種機制來進行判斷。kruskal演算法用了乙個非常聰明的方法,就是運用集合避圈:如果所選擇加入的邊的起點和終點都在t的集合中,那麼就可以斷定一定會形成迴路(圈)。其實就是我們前面提到的「避圈法」:邊的兩個結點不能屬於同一集合。

步驟1:初始化。將圖g的邊集e中的所有邊按權值從小到大排序,邊集te=,把每個頂點都初始化為乙個孤立的分支,即乙個頂點對應乙個集合。

步驟2:在e中尋找權值最小的邊(i,j)。

步驟3:如果頂點i和j位於兩個不同連通分支,則將邊(i,j)加入邊集te,並執行合併操作,將兩個連通分支進行合併。

步驟4:將邊(i,j)從集合e中刪去,即e=e−。

步驟 5:如果選取邊數小於n−1,轉步驟2;否則,演算法結束,生成最小生成樹t。

#include #include #include #include using namespace std;

const int n=111;

int nodeset[n];//結點的集合。

int n;//結點的數量

int m;//邊的數量

struct edge //邊的結構體

e[n*n];

//構造乙個鄰接矩陣

bool cmp(edge x,edge y) //將權值從小到大排序的乙個函式

void init(int n) //初始化結點函式(相當於把每個結點都當成孤立的連通分支)

}int merge(int a ,int b) //合併集合的函式(避圈法)

}return 1;

}int kruskal(int n)

sort(e,e+m,cmp); //將邊值從小到大排序

int ans=kruskal(n);

cout << "最小生成樹的最小花費是:"

}

貪心的kruskal最小生成樹演算法

description xx星有許多城市,城市之間通過一種奇怪的高速公路sars super air roam structure 超級空中漫遊結構 進行交流,每條sars都對行駛在上面的flycar限制了固定的speed,同時xx星人對 flycar的 舒適度 有特殊要求,即乘坐過程中最高速度與最...

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 ...