本次,我主要給大家講一講有關這一題的Prim算法
首先我們來討論一下:
什麼是最小生成樹?
- 無迴路,且包含原圖中的n-1條邊。
- 包含原圖中的全部頂點。
- 邊的權重和在所有其他生成樹中最小。
- 最小生成樹存在,則該圖一定連通。反過來一樣,圖連通,則最小生成樹一定存在
那麼如何構建滿足以上條件的生成樹?
Prim算法構建最小生成樹,
簡單來說就是在圖中,從某一頂點出發,逐步構建,讓一棵小樹逐漸長大。
用一個例子來說明更清晰點吧!首先看下面一張無向網圖:
要構造這張圖的最小生成樹,首先,假設我們從V0頂點開始出發,
也就是以V0爲根結點開始建樹,接着往外擴展,從與V0頂點相鄰的頂點中找出權值最小的頂點,可以看到是V6,所以把V6和V0連接起來。
也就是把V6收錄進了這棵最小生成樹中了。
接着繼續,從當前樹中頂點的鄰接點中 (也就是V0和V6的鄰接點中,找出權值最小的頂點)。可以看到是V1,所以把V1也接入最小生成樹中。
然後繼續,到V2結點,也接入最小生成樹中
因爲不能形成迴路,
所以V2和V6之間不能連接(雖然權值最小,等於3)。
V0和V1之間也不能連接。所以只能V6和V4連接
最後V4和V5連接,V4再和V3連接,就完成了這棵最小生成樹的構建了。
本圖爲最小生成樹的最終模型
好了,基本Prim算法已實現,迴歸正題
題目傳送門
首先,按照做題的方法,我們先把數據全部讀入;
然後把兩條田地修管子的費用全部求出來,注意本題是無向的;
所以way[i][j]=way[j][i];
還要注意一點,就是如果way[i][j]<c要把way[i][j]設爲達到不了 (即設成很大的數)
接着用一個p[]存儲當前點有沒有用過;
剩下的我給個關鍵代碼吧 (就是Prim算法關鍵部分):
for(int i=1;i<=n;i++) cnt[i]=way[1][i];
for(int i=1;i<=n-1;i++)
{
int k=0,ji=maxn;
for(int j=1;j<=n;j++) if(cnt[j]<ji&&!p[j]) ji=cnt[j],k=j;
if(ji==maxn){
printf("-1");
return 0;
}
ans+=ji;
p[k]=1;
for(int j=1;j<=n;j++)
if(cnt[j]>way[k][j]&&!p[j]) cnt[j]=way[k][j];
}
最後輸出就可以了