生成樹
生成樹是連通圖的最小連通子圖。所謂最小是指:若在樹中任意增加一條邊,則將出現乙個迴路;若去掉一條邊,將會使之變成非連通圖。按照該定義,n個頂點的連通網路的生成樹有n個頂點,n-1條邊。
可知用不同的遍歷圖的方法,可以得到不同的生成樹;從不同的頂點出發,也可能得到不同的生成樹。
最小生成樹
生成樹各邊的權值總和稱為生成樹的權,權最小的生成樹稱為最小生成樹。
常見的構造最小生成樹的方法有prim演算法和kruskal演算法。
下面介紹prim演算法
prim演算法
prim演算法通常以鄰接矩陣作為儲存結構。
它的基本思想是以頂點為主導地位,從起始頂點出發,通過選擇當前可用的最小權值邊把頂點加入到生成樹當中來:
1.從連通網路n=中的某一頂點u0出發,選擇與它關聯的具有最小權值的邊(u0,v),將其頂點加入到生成樹的頂點集合u中。
2.以後每一步從乙個頂點在u中,而另乙個頂點不在u中的各條邊中選擇權值最小的邊(u,v),把它的頂點加入到集合u中。如此繼續下去,直到網路中的所有頂點都加入到生成樹頂點集合u中為止。
可行性證明:
設prim生成的樹為g0
假設存在gmin使得cost(gmin)0)
則在gmin中存在(u,v)不屬於g0
將(u,v)加入g0中可得乙個環,且(u,v)不是該環的最長邊
這與prim每次生成最短邊矛盾
故假設不成立,得證.
下面看具體資料和模擬過程
現在有乙個儲存結構為鄰接矩陣的g,有9個頂點,它的arc二維陣列如上圖所示。
於是prim演算法的**如下,其中infinity為權值極大值,不妨設為0xfffffff,maxvex為頂點個數最大值,此處大於等於9即可。
void minspantree_prim(mgraph g)
,而adjvex則全部為0。此時,已經完成了整個初始化的工作,準備開始生成。
4.第13~35行,整個迴圈過程就是構造最小生成樹的過程。
5.第14~16行,將min設定為了乙個極大值0x3fffffff,它的目的是為了之後找到一定範圍內的最小權值。j是用來做頂點下標迴圈的變數,k是用來儲存最小權值的頂點下標。
6. 第17~24行,迴圈中不斷修改min為當前lowcost陣列中最小值,並用k保留此最小值的頂點下標。經過迴圈後,min=10,k=1。第19行if判斷的lowcost[j]!=0表示已經是生成樹的頂點不參與最小權值的查詢。
7.第25行,因k=1,adjvex[1]=0,所以列印結果為(0,1),表示v0至v1邊為最小生成樹的第一條邊。如下圖所示:
8.第26行,此時因k=1,我們將lowcost[k]=0就是說頂點v1納入到最小生成樹中。此時lowcost陣列值為。
9.第27~33行,j迴圈由1至8,因k=1,查詢鄰接矩陣的第v1行的各個權值,與lowcost的對應值比較,若更小則修改lowcost值,並將k值存入adjvex陣列中。因第v1行有18、16、12均比0x3fffffff小,所以最終lowcost陣列的值為:。adjvex陣列的值為:。這裡第30行if判斷的lowcost[j]!=0也說明v0和v1已經是生成樹的頂點不參與最小權值的對比了。
10.再次迴圈,由第14行到25行,此時min=11,k=5,adjvex[5]=0。因此列印結構為(0,5)。表示v0至v5邊為最小生成樹的第二條邊,如下圖所示:
11.接下來執行到33行,lowcost陣列的值為:。adjvex陣列的值為:。
12.之後經過類似的模擬,如下圖:
總結使用鄰接矩陣作為儲存結構的prim演算法的時間複雜度為o(v2),如果使用二叉堆與鄰接表表示的話,prim演算法的時間複雜度可縮減為o(e log v),其中e為連通圖的邊數,v為頂點數。
如果使用較複雜的斐波那契堆,則可將執行時間進一步縮短為o(e + v log v),這在連通圖足夠密集時(邊較多,即e滿足ω(v log v))可較顯著地提高執行速度。
求minispan_tree中longest edge
vector中存每個點所連邊的序號 通過邊集陣列索引
//求minispan_tree中longest edge
//o(n^2)
//vector中存每個點所連邊的序號 通過邊集陣列索引
#include#include#includeusing namespace std;
struct edge
};const int maxn=10010;
const int inf=0x3f3f3f3f;
int ans;
vectoredges;
vectorg[maxn];
int n,m;
void addedge(int u,int v,int w)
int adjvex[maxn];//最小生成樹上每個點的前驅
int lowcost[maxn];//前驅到這個點的距離,即目前最小生成樹中到該點的最短距離
bool v[maxn];//是否在生成樹中的標記
void prim()
int adjvex[maxn];//最小生成樹上每個點的前驅
int lowcost[maxn];//前驅到這個點的距離
int v[maxn];//是否在生成樹中的標記
void prim()
{ for(int i=1;i<=n;++i) lowcost[i]=inf;
lowcost[1]=0;
for(int i=1;i<=n;++i) adjvex[i]=0,v[i]=0;
adjvex[1]=1;
for(int i=1;i<=n;++i){
//for(int i=1;i<=n;++i) cout<
最小生成樹(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...