最小生成樹(Prim演算法和Kruskal演算法)

2022-04-05 16:32:46 字數 3186 閱讀 2714

給定乙個無向圖,如果它的某個子圖中任意兩個頂點都互相連通並且是一棵樹,那麼這棵樹就叫生成樹。如果邊上有權值,那麼使得邊權和最小的生成樹叫做最小生成樹(mst,minimum spanning tree)

比如讓你為乙個鎮的九個村莊架設通訊網路,每個村莊相當於乙個頂點,權值是村與村之間可通達的直線距離,要求你必須用最小的成本完成這次任務;或者

村莊之間建公路,連通n個村莊要n-1條路,如何讓建路成本最低之類的問題。

①該演算法是構建最小生成樹的演算法之一。它是以某頂點為起點,不斷新增各頂點上最小權值的邊,來構建最小生成樹。

②演算法流程:

第一步:設圖g頂點集合為u,首先任意選擇圖g中的一點作為起始點a,將該點加入集合v;

第二步:從集合u中找到另一點b使得點b到v中任意一點的權值最小,此時將b點也加入集合v;

以此類推,現在的集合v=,再從集合u中找到另一點c使得點c到v中任意一點的權值最小,此時將c點加入集合v;直至所有頂點全部被加入v,此時就構建出了一棵mst。

#include #include 

#define int_max 1000000000

using

namespace

std;

int matrix[100][100];//

鄰接矩陣

bool visited[100];//

標記陣列

int path[100];//

記錄生成樹路徑

int lowcost[100];//

邊的權值

int vertex_num,arc_num;//

頂點數,弧數

int sum;//

權值總和

int source;//

源點void prim(int

source);

intmain()

cout

<< "

請輸入起點(<

"<< vertex_num << "):"

; cin >>source;

prim(source);

cout

<< "

最小生成樹權和為:

"<< sum <

cout

<< "

最小生成樹路徑為:\n";

for (int i = 0; i < vertex_num; i++)

if (i !=source)

cout

<< i << "

----

"<< path[i] <

return0;

}void prim(int

source)

int min_cost,min_cost_index;//

最小的權值,和其下標

sum=0

;

for(int i=1;i//

找除源點外的n-1個點,如果這裡寫多了,

//那麼下邊的for裡if進不去,那麼sum的值也會錯誤

min_cost=int_max;

for(int j=0;j//

遍歷所有頂點

if(visited[j]==false&&lowcost[j]//

找到與源點的權值最小的點

min_cost=lowcost[j];

min_cost_index=j;}}

visited[min_cost_index]=true;//

講找到的頂點進行標記

sum+=min_cost;//

權值總和

for(int j=0;j)}}

}

摘自

①該演算法是構建最小生成樹的另乙個演算法,其是對邊進行操作,來構建最小生成樹的。

②演算法流程:

第一步:把所有的邊按權值從小到大排列。

第二步:按照順序選取每條邊,如果這條邊的兩個端點不屬於同一集合,那麼就將它們合併。

重複第二步,直到 所有的點都屬於同乙個集合。     

第二步用並查集來實現,又因為每次都選的權值最小的,所以這其實就是運用並查集的貪心演算法。

③為什麼這樣做就可以構建最小生成樹呢?因為n個頂點只需要n-1條邊就夠了,那麼選哪n-1條呢,為了讓權值和最小,當然選從小到大排序的前n-1條邊嘍。

#include #include 

#define max_int 100

using

namespace

std;

struct edgeedge[max_int];

int par[max_int];//

i的父親的編號

int rank[max_int];//

i的高度

int vertex_num,arc_num;//

頂點數,弧數

int case_num;//

測試組數

int sum;//

權值總和

void init(int n);//

初始化int find(int x);//

查詢根節點並且壓縮路徑

bool unite(int x,int y);//

合併bool compare(const edge&a,const edge&b);

intmain()

sort(edge,edge+arc_num,compare);

cout

<

最小生成樹的路徑為:

"<

intj;

for(j=0;j)

}if(j==arc_num)

else

if(j

case_num--;

}return0;

}void init(intn)}

int find(int

x)else

}bool unite(int x,int

y)else

else

return

true

; }

}bool compare(const edge&a,const edge&b)

prim演算法時間複雜度為

,與網中的邊數無關,適用於求邊稠密的網的最小生成樹。

kruskal演算法時間複雜度為

,適用於求稀疏的網的最小生成樹。

最小生成樹(prim演算法)

最小生成樹是資料結構中圖的一種重要應用,它的要求是從乙個帶權無向完全圖中選擇n 1條邊並使這個圖仍然連通 也即得到了一棵生成樹 同時還要考慮使樹的權最小。prim演算法要點 設圖g v,e 其生成樹的頂點集合為u。把v0放入u。在所有u u,v v u的邊 u,v e中找一條最小權值的邊,加入生成樹...

最小生成樹 Prim演算法

prim 演算法 以領接矩陣儲存 圖g bool b i 表示頂點i是否被訪問,初始化時候memset b,false,sizeof b b 0 value,表示從第0個節點開始。用value i 表示節點i到最小生成樹a中定點的最小距離。例如value 1 a 0 1 int sum記錄權值和 i...

最小生成樹 prim 演算法

一 演算法描述 假設存在連通帶權圖g v,e 其中最小生成樹為t,首先從圖中隨意選擇一點s屬於v作為起始點,並將其標記後加入集合u 中。然後演算法重複執行操作為在所有v屬於u,u屬於v u的邊 v0,u0 屬於e中找一條代價最小的邊並加入集合t,同時將u0併入u,直到u v為止。這是,t中必有n 1...