稠密圖
//稠密圖-鄰接矩陣
template
class densegraph
//析構函式
~densegraph()
//返回節點個數
intv()
//返回邊的個數
inte()
//向圖中新增乙個邊,權值為weight
void
addedge
(int v,
int w,weight weight)
g[v]
[w]= new edge
(v,w,weight);if
(v!=w &&
!directed)
g[w]
[v]= new edge
(w,v,weight)
; m++;}
//驗證圖中是否有從v到w的邊
bool hasedge
(int v,
int w)
//顯示圖的資訊
void
show()
cout<
//鄰邊迭代器,傳入乙個圖和乙個頂點
//迭代在這個圖中和這個頂點相連的所有邊
class adjiterator
~adjiterator()
//f返回圖g中與頂點v相連線的第乙個邊
edge
*begin()
//返回圖g中與頂點v相連線的下乙個邊
edge
*next()
//檢視是否已經迭代完了圖g中與頂點v相連線的所有邊
bool end()
};};
稀疏圖
//稀疏圖
template
class sparsegraph
~sparsegraph()
//返回節點個數
intv()
//返回邊的個數
inte()
//向圖中新增乙個邊,權值為weight
void
addedge
(int v,
int w,weight weight)
//驗證圖中是否有從v到w的邊
bool hasedge
(int v,
int w)
void
show()
}//鄰邊迭代器,傳入乙個圖和乙個頂點
//迭代在這個圖中和這個頂點相連的所有邊
class adjiterator
//返回圖g中與頂點v相連線的第乙個邊
edge
*begin()
//返回圖g中與頂點v相連線的下乙個邊
edge
*next()
bool end()
};};
切分定理(cut property)
把圖中的結點分為兩部分,成為乙個切分(cut)
如果乙個邊的兩個端點,屬於切分(cut)不同的兩邊,這個邊稱為橫切邊
切分定理:給定任意切分,橫切邊中權值最小的邊必然屬於最小生成樹lazy prime:
在這裡選取權值最小的邊的時候要利用到最小堆(之前講過)
以下為prime演算法:
//使用prim演算法求圖的最小生成樹
template
class lazyprimmst
public:
//建構函式,使用prim求圖的最小生成樹
lazyprimmst
(graph &graph):g
(graph),pq
(minheap
>
(graph.e(
)))//計算最小生成樹的權值
mstweight = mst[0]
.wt()
;for
(int i=
1;isize()
;i++
) mstweight+
=mst[i].wt
();}
//析構函式
~lazyprimmst()
//返回最小生成樹的所有邊
vector
>
mstedges()
//返回最小生成樹的權值
weight result()
};#endif
// lazyprimmst_h_included
測試**:
// 測試有權圖和有權圖的讀取
intmain()
執行結果:
進行優化使之時間複雜度為o(elo**)
維護乙個indexminheap資料結構
最小索引堆中的元素個數和圖中的頂點個數一致,在堆操作這裡提高了效率,遍歷邊的次數也變小了。
//使用優化的prim演算法求圖的最小生成樹
template
class primmst
//如果考慮過這個端點,但現在的邊比之前考慮的邊更短,則進行替換
else
if(e->wt(
)->wt(
))}}
}public:
//建構函式,使用prim演算法求圖的最小生成樹
primmst
(graph &graph):g
(graph)
,ipq
(indexminheap<
double
>
(graph.v(
))) mst.
clear()
;//prim
visit(0
);while
(!ipq.
isempty()
) mstweight = mst[0]
.wt()
;for
(int i=
1;isize()
;i++
) mstweight+
=mst[i].wt
();}
~primmst()
vector
>
mstedges()
weight result()
};#endif
// primmst_h_included
思路:每次都找最短的那邊條,只要不構成環,那條邊一定是最小生成樹的邊。
為什麼呢?因為根據這條最短邊,我們總能找到乙個切分,使得該邊為這個切分下的橫切邊的最短邊。
如果判斷加入邊後有沒有環的存在呢?使用並查集
//kruskal演算法
template
class kruskalmst
//建立乙個並查集,來檢視已經訪問的節點的聯通情況
unionfind uf =
unionfind
(graph.v(
));while
(!pq.
isempty()
&& mst.
size()
< graph.v(
)-1)
mstweight = mst[0]
.wt()
;for
(int i=
1;isize()
;i++
) mstweight+
=mst[i].wt
();}
~kruskalmst()
//返回最小生成樹的所有邊
vector
>
mstedges()
//返回最小生成樹的權值
weight result()
};#endif
// kruskalmst_h_included
最小生成樹問題如果橫切邊有相等的邊,根據演算法的具體實現,每次選擇乙個邊,此時,圖存在多個最小生成樹。
延伸問題:對於乙個圖有多少個最小生成樹??
vessotsky『s algorithm
將邊逐漸的新增到生成樹中,一旦形成環,刪除環中權值最大的邊(難度比較大)。
最小生成樹演算法
由帶權的連通圖生成的數的各邊加起來稱為生成樹的權,把權值最小的生成樹稱為最小生成樹 minimum spanning tree 簡稱為mst 構造最小生成樹的方法就是利用mst性質,一條一條地選擇可以加入的邊。下面介紹兩種用於構造最小生成樹的演算法,其中第一種演算法稱為prim演算法,第二種演算法稱...
最小生成樹演算法
乙個最簡單的最小生成樹 圖結構練習 最小生成樹 time limit 1000ms memory limit 65536k 有n個城市,其中有些城市之間可以修建公路,修建不同的公路費用是不同的。現在我們想知道,最少花多少錢修公路可以將所有的城市連在一起,使在任意一城市出發,可以到達其他任意的城市。輸...
演算法 最小生成樹
前言 最小生成樹是在乙個給定的無向圖中求一棵樹,這棵樹包含無向圖中的所有頂點,且樹中的邊都來自無向圖中的邊,並且要滿足整棵樹的邊權之和最小。1 最小生成樹是樹,其邊數等於頂點數減1,且不會有環 2 對於給定的圖最小生成樹可以不唯一,但是邊權之和一定是唯一的。3 其根節點可以是這棵樹上的任何乙個節點,...