經典演算法之Kruskal演算法

2021-08-21 16:19:43 字數 1866 閱讀 3805

生成最小生成樹,與prim演算法不同的是,prim是以頂點為關鍵來生成最小樹的,而kruskal是以邊為關鍵來生成最小數。

1、將v個頂點,l條邊的圖g中所有的邊按權值大小從小到大排序,這一步可以直接用庫函式qsort或者sort。

2、從權值小的邊開始依次選取,若選取的邊使生成樹t不形成迴路,則選之;若選取的邊使生成樹形成迴路,則將其捨棄;如此進行下去,直到選取v-1條邊為止。

在上述的方法中,最關鍵的地方在於判斷新加入的邊與生成樹是否構成迴路,判斷圖是否構成迴路有很多方法,這裡我們使用並查集

來判斷圖是否構成迴路。

將頂點劃分到不同集合中,每個集合中的頂點表示乙個無迴路的連通分量。演算法開始時,將n個頂點劃分到n個集合中,每個集合乙個頂點,表示頂點之間互不相通。當選取一條邊時,若它的兩個頂點屬於不同的集合,則表明連通了兩個不同的連通分量,因每個連通分量沒有迴路,所以連通後仍然不會有迴路,因此保留這條邊;同時把兩個集合進行合併成為乙個集合。若選取的邊屬於同乙個集合,則捨棄此邊。

我們以hdu1863為例:

/* father[x]表示x的父節點 */

int father[n];

/* rank1[x]表示x的秩 */

int rank1[n];

int v,l; // v 頂點數 l 邊數

//定義結構體,用來存放圖中的頂點,邊和權值

typedef struct kruskal kruskal;

//過載cmp,使kruskal陣列按權值的大小從 小——>大 排序

bool cmp(const kruskal & a, const kruskal & b)

//初始化father和rank1,將n個頂點劃分到n個集合中,每個集合乙個頂點,表示頂點之間互不相通

void ini(int size1)

}//查詢x的父節點

int find1(int x)

//合併節點x和y

bool unions(int x,int y)

else

return true;

}int main()

{ //邊值和

//權值和

//迴圈終止條件

int ltotal,sum,flag;

while(cin>> l >> v && l){

//定義結構體g

kruskal g[n];

ltotal=0,sum=0,flag=0;

//初始化集合

ini(v);

//輸入

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

cin >> g[i].a >> g[i].b >> g[i].value;

//排序

貪心經典演算法 Kruskal演算法

kruskal演算法的高效實現需要一種稱作並查集的結構。我們在這裡不介紹並查集,只介紹kruskal演算法的基本思想和證明,實現留在以後討論。kruskal演算法的過程 1 將全部邊按照權值由小到大排序。2 按順序 邊權由小到大的順序 考慮每條邊,只要這條邊和我們已經選擇的邊不構成圈,就保留這條邊,...

Prim演算法 Kruskal演算法

一 prim演算法 1 要求 1 生成一顆連通的樹 2 生成樹 包含全部頂點,v 1條邊,沒有迴路,並且新增一條邊會變成有迴路 3 權重和最小 2 過程模擬 最重要 貪心的思想,每一步都要選擇權值最小的,這棵樹所有跟頂點相連的邊中最小的。從根節點開始,讓樹慢慢的長大。過程 從v1開始 跟v1有聯絡的...

Prim演算法 Kruskal演算法

prim演算法 kruskal演算法 prim演算法和kruskal演算法,都是用來找出圖中最小生成樹的演算法,兩個演算法有些小差別。prim演算法 又稱普里姆演算法,以圖上的頂點為出發點,逐次選擇到最小生成樹頂點集距離最短的頂點為最小生成樹的頂點,並加入到該頂點集,直到包含所有的頂點。1.選擇一出...