生成最小生成樹,與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.選擇一出...