Prim演算法解決最小生成樹

2022-05-02 11:57:07 字數 1652 閱讀 9652

一、最小生成樹問題

什麼是最小生成樹問題?給你乙個帶權連通圖,需要你刪去一些邊,使它成為一顆權值最小的樹。

二、prim演算法

1)輸入:輸入乙個帶權連通圖,頂點集合v,邊集合e

2)初始化:vnew=,x為任意乙個頂點,作為起始點,enew={},為空

3)在集合e中選擇權值最小的邊,其中u為集合vnew中的頂點,而v不在集合vnew中但在v中,(若有多條滿足條件且權值相同時,可任選其中一條)

4)將v收錄集合vnew中,將收錄enew中

5)重複步驟4、5,直到所有的頂點都被收錄到vnew中

6)輸出:輸出由vnew和enew所描述的最小生成樹

證明:這就是乙個樸素的貪心,我們只需證明這種貪心策略是正確的。先看一下這個性質:

mst性質:設g=(v,e)是乙個連通網路,u是頂點集v的乙個真子集。若(u,v)是g中一條「乙個端點在u中(例如:u∈u),另乙個端點不在u中的邊(例如:v∈v-u),且(u,v)具有最小權值,則一定存在g的一棵最小生成樹包括此邊(u,v)。

假如通過其他途徑,已經得到一顆不包含(u,v)的最小生成樹,那麼把(u,v)加入到這棵生成樹,必定成環,由於在某點沒有選(u,v),則必定可以在環上找到乙個權值不小於(u,v)的邊,刪去此邊,用(u,v)代替,仍是一顆最小生成樹且總權值更小。所以由反證法知,一定存在一棵最小生成樹包含(u,v)。所以可以通過每次選擇符合條件的權值最小邊,來得到其中一種最小生成樹。

三、演算法實現

思路:這裡用鄰接矩陣a儲存圖(因為prim適合稠密圖,時間複雜度一般為o(n^2)),用陣列lowcost[maxn]記錄未收錄頂點到vnew的最小費用,用vis[maxn]記錄是否已收錄。

1)任取一頂點s,收錄到vnew中(這裡簡化為vis[s] = true)

2) 初始化,將lowcost[x]初始化為到s的費用

將下列步驟進行n-1次

3)找到最小的lowcost[x]

4)若沒有找到符合條件的最小lowcost[x],跳出迴圈

5)將x收錄到vnew

6)  更新lowcost[ ]  (因為新收錄的頂點可能影響lowcost)

7)若有頂點未被收錄,說明圖不連通

**:

#include#include

#include

const

int inf = 0x3f3f3f3f

;const

int maxn = 100 + 10

;bool

vis[maxn];

intlowcost[maxn];

intcost[maxn][maxn];

//點是從0 ~ n-1

//耗費矩陣cost

int prim(int cost[maxn], int s, int

n) }

if (i < n - 1 && pos < 0) return -1

; vis[pos] = true

; ans +=minc;

for (int j = 0; j < n; j++)

}return

ans;

}

view code

四、演算法優化

據說可以用二叉堆、斐波那契堆等,先給自己挖乙個坑,日後再補吧。

最小生成樹(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...