使用貪心演算法解決最小生成樹

2021-09-11 13:20:28 字數 1697 閱讀 2676

生成樹的定義:對於乙個圖g,獲取g的邊使得所有的頂點都連線到。最小生成樹(mst minimun spanning tree):給定圖g(v,e),以及對應的邊的權重,獲取一顆總權重最小的生成樹。

樹的定義:連線的無環圖

找到所有的生成樹,然後計算權重最小的

考慮上面的圖,一但紅色線選定,對於接下了的標號為1,..,n的所有節點點,左右節點都只需要二選一即可得到不同的生成樹,這樣的選擇有

最優子結構:有多個子結構的最優解最終組成整個問題的最優解

貪心演算法的選擇特定,會使得區域性最優解最終也是全域性最優解

假如邊e=是某個mst的一條邊,通過對合併這兩個頂點為乙個新的頂點(這種操作稱作contract e),將有多條邊同時連線多個頂點的合併成乙個權重最小的邊保留,其它邊的連線形式保持不變。可以證明假設t'是g/e(不包含e的g)的mst,那麼t'u也是g的mst

假設t*(

而w(t'ue)=w(t')+w(e),所以

因而成立

假設有任意的cut(s,v-s),選取e,使得e是所有crossing cut的最小權重的邊

紅色的線即 crossing cut的邊

假設t是g的乙個mst,那麼它必定存在一條邊e'=橫跨s和v/s,由於w(e)<=w(e'),可以構造t'=t/u=w(t)-w(e')+w(e)<=w(t),也就是說t'也是mst,e屬於某個mst。

維護乙個優先順序佇列q,它的節點u.key=min

初始的圖如下

選取節點s in s,其它的為v-s 按照初始化的規則得到

然後獲取最小key的節點,顯然他就是s

獲取s的所有鄰接表,比較crossing cut的邊的權值和當前q中儲存的key的大小,保留小的,得到

再找到q中最小的為a,將兩者記下來

再檢視所有s的鄰接表,更新q的權值,得到

獲取最小值為5,將它放入s中

再次更新q得到

獲取最小是為6,得到

再更新q

最小值為8

更新q得到

最小值為3

更新q得到

最小值為9

更新q得到

最小值為15

最終得到mst為

在整個過程中,涉及v次的從優先順序佇列中獲取最小值,以及邊兩倍次的減少key的值,所以總的時間為

使用斐波那契堆可以達到vl**+e

核心思想:全域性最小的corssing cut邊必定屬於最小生成樹,這個過程不能生成環,需要追蹤兩個節點是否已經互相連線了

追蹤的資料結構是 union-find 結構,包含3個功能,make-set:建立乙個集合;find-set:找到當前元素在那個集合;union:合併集合

延伸閱讀 union-find資料結構與ackermann函式

在使用union-find資料結構的基礎上能夠做到時間為o(elge+eα(v)),假設權重為正整數而且最大值是個常量,那麼排序可以達到常量的時間,這個時候,演算法所需要的時間就是o(e),整體不prims演算法要好

最快的mst 演算法執行期望時間是o(v+e),karger, klein, and tarjan 1993發明

貪心演算法 最小生成樹 Prim演算法

乙個無向帶權圖g v,e 其中n個頂點vertex,以及連線各個頂點之間的邊edge,可能有些頂點之間沒有邊,每條邊上的權值都是非負值。生成樹 g的乙個子圖,包含了所有的vertex,和部分的edge。最小生成樹 所有的生成樹中,各條edge上的權值總和最小的乙個。例子 設計通訊網路時,各個城市之間...

貪心演算法 最小生成樹 Kruskal演算法

關於最小生成樹的概念,請參考前一篇文章 prim演算法。kruskal演算法 不停地迴圈,每一次都尋找兩個頂點,這兩個頂點不在同乙個真子集裡,且邊上的權值最小。把找到的這兩個頂點聯合起來。初始時,每個頂點各自屬於自己的子集合,共n個子集合。每一步操作,都會將兩個子集合融合成乙個,進而減少乙個子集合。...

貪心演算法之Prim最小生成樹

滿足貪心演算法的條件是都滿足動態規劃的,只是貪心演算法的條件更強,不僅前乙個步驟的解可以用到後一步,而且前一步的解是子問題的最優解,最後能夠得到全域性的最優解。prim演算法是乙個求最小生成樹的演算法。表示圖g 有鄰接表 用於稀疏矩陣 和鄰接矩陣 用於稠密矩陣 下面我給的例項適合用稀疏矩陣。聽了大概...