次小生成樹 Prim

2021-10-17 15:47:16 字數 2370 閱讀 9771

我們最常見的是最小生成樹,我們最長使用的是prim和kruskal演算法,乙個是對點進行處理,乙個是對邊進行處理,對於次小生成樹來說我們同樣可以使用這兩個方法進行處理,這裡我們先以prim的寫法為例。

首先我們要清楚的是什麼是最小生成樹:乙個有 n 個結點的連通圖的生成樹是原圖的極小連通子圖,且包含原圖中的所有 n 個結點,並且有保持圖連通的最少的邊。所以在這之前我們需要先了解幾個結論:

①如果我們要換掉其中的一條邊的話新得到的生成樹的權值之和一定小於等於原最小生成樹的權值之和;

證明:換掉一條邊之後得到的生成樹的權值之和小於原最小生成樹了,那麼換掉之後的應該才是最小生成樹,與定義不符,但是因為最小生成樹不一定唯一,所以用可能等於。

②如果我們在最小生成樹的基礎上任意再加入一條邊,會形成乙個環;

證明:最小生成樹的邊有(v - 1)條,如果再加入一條邊就有(v)條邊了,(v)個頂點(v)條邊一定至少會形成乙個環,因為一條邊連線兩個點,如果有 n 條邊,那麼就用到了 「2n」 個點,因為我們有 n 個點,假設我們(n-1)個點只使用了一次,即所有的點都連在了乙個點上,即就有(n-1)條邊連在了中心那個點上,而我們又多出來了一條邊,所以肯定會形成乙個環;

有了上述的兩個結論我們再來想次小生成樹,我們先得到乙個最小生成樹,然後我們再往裡面加入一條我們在構建這個最小生成樹的時候沒有用到的邊,這樣就形成了乙個環,然後我們再把形成的這個環中最大的那條邊(不是我們新加入的那條)刪除掉,這樣我們就得到了乙個新的生成樹,這個新的生成樹的權值之和一定大於等於原最小生成樹之和,我們只需要把剩餘的邊遍歷一遍找出那個最小的新生成的最小生成樹即可。

我們會發現這個地方有一點難實現的地方,就是如果我們要新加入兩個邊,難道我們要先用bfs找到這個環,然後再找到這個環的最大值嗎?且不說是否容易實現,單單是時間複雜度我們就難以承受,所以我們肯定不會這樣實現在競賽考試中(有興趣的同學可以寫寫試試這種「傻」方法,相信寫完之後對遞迴的理解肯定有乙個很大的提公升),這一步我們完全可以用乙個maxx陣列來實現:

maxx[i][j]:在我們得到的最小生成樹中從 i 到 j 最大的那條邊的長度,那麼我們再加入邊的時候就可以直接得到我們需要替換掉的那條最大的邊的長度了:

//sum:最小生成樹的權值之和

//used[i][j]:i到j的邊是否是最小生成樹中的邊

//cost[i][j]:邊i到j的權值,如果i到j不存在邊就是inf

for

(int i=

1;i<=n;i++)}

}}

大致實現過程:

1、遍歷dist陣列,找到dist最小的那個點(跟prim一樣),把這個點標記為已經訪問過,然後把這條邊加入到最小生成樹中(讓這條邊的used變成true),在這裡我們需要使用到的pre陣列,來儲存這條邊是由哪個點到達的,即pre[i]到 i 就是我們所加入的這條邊;

2、對maxx陣列進行更新,之前都是其他點到pre[i]的最大距離,現在要看加上這條邊之後有沒有最這些邊有更新(只看被訪問過的點),如果這個點沒被訪問過並且cost[p][j]#include

#include

using

namespace std;

const

int maxn =

1001

;const

int inf =

0x7f7f7f7f

;bool vis[maxn]

;int dist[maxn]

;int pre[maxn]

;int maxx[maxn]

[maxn]

;bool used[maxn]

[maxn]

;int cost[maxn]

[maxn]

;int n,m;

intprim()

for(

int i=

1;iif(p ==-1

) ans +

= minc;

//最小生成樹

vis[p]

=true

; used[p]

[pre[p]

]= used[pre[p]

][p]

=true

;for

(int j=

1;j<=n;j++)if

(!vis[j]

&& cost[p]

[j]}return ans;

}int

main()

int sum =

prim()

;int ans = inf;

for(

int i=

1;i<=n;i++)}

}}cout << ans << endl;

return0;

}

次小生成樹(Prim)

這裡的思路就是先用prim演算法求的最小生成樹,然後在prim演算法中新增乙個max陣列,用max陣列存放兩點間的最大距離,並且用乙個use陣列 布林型別 存放是否使用過該邊,最後再在沒有使用的變進行遍歷,找出最小,求的最小生成樹!下面介紹一下利用prim求次小生成樹的主要步驟。1.先求出來最小生成...

次小生成樹 prim求法入門

結合例題和 以及注釋可能會更好理解一些 poj 1679 the unique mst 次小生成樹 設g v,e,w 是連通的無向圖,t是圖g的一顆最小生成樹。如果有另一棵樹t1,滿足存不存在樹t t t1 則稱t1是圖g的次小生成樹。次小生成樹一般又最小生成樹的鄰集求得。鄰集的概念 由t進行一次可...

次小生成樹 prim和kruskal

prim 先用prim求出最小生成樹t,在prim的同時,用乙個矩陣maxd u v 記錄 在t中鏈結任意兩點u,v的唯一的路中權值最大的那條邊的權值,這是很容易做到的,因為prim是每次增加乙個結點s,在此需要儲存節點和其父節點,採用dp,則最大權值要麼是新加入的邊,要麼是父節點到起始點的採用dp...