1. 程式人生 > >7-10 公路村村通 (30 分)(最小生成樹)+prim詳解

7-10 公路村村通 (30 分)(最小生成樹)+prim詳解

現有村落間道路的統計資料表中,列出了有可能建設成標準公路的若干條道路的成本,求使每個村落都有公路連通所需要的最低成本。

輸入格式:

輸入資料包括城鎮數目正整數N(≤1000)和候選道路數目M(≤3N);隨後的M行對應M條道路,每行給出3個正整數,分別是該條道路直接連通的兩個城鎮的編號以及該道路改建的預算成本。為簡單起見,城鎮從1到N編號。

輸出格式:

輸出村村通需要的最低成本。如果輸入資料不足以保證暢通,則輸出−1,表示需要建設更多公路。

輸入樣例:

6 15

1 2 5

1 3 3

1 4 7

1 5 4

1 6 2

2 3 4

2 4 6

2 5 2

2 6 6

3 4 6

3 5 1

3 6 1

4 5 10

4 6 8

5 6 3

輸出樣例:

12

注意點:prim演算法可以看做是由dijkstra演算法稍微改動一下就能得到,dijkstra是把每個點求出與源點的最短距離,而prim是把每個點新增到最小生成樹裡面就可以了,所有改動兩行便可,詳見程式碼。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
using namespace std;
const int maxn=1001;
const int inf=999999;
int n,m;
int dis[maxn],e[maxn][maxn];
bool visit[maxn];
int mincost=inf;
void prim(){
    int cnt=0,cost=0;
    dis[1]=0;
    for(int i=1;i<=n;i++){
        int u=-1,minn=inf;
        for(int j=1;j<=n;j++){
            if(visit[j]==false&&dis[j]<minn){
                u=j;
                minn=dis[j];
            }
        }
        if(u==-1) break;
        visit[u]=true;
        cost+=dis[u];
        cnt++;
        for(int v=1;v<=n;v++){
            if(visit[v]==false&&e[u][v]!=inf&&e[u][v]<dis[v])//和傳統dijkstra演算法的區別在於這裡,直接新增到生成樹裡,而不是源點
                dis[v]=e[u][v];
        }
    }
    if(cnt==n) cout<<cost<<endl;
    else cout<<"-1\n";
}
int main()
{
    fill(dis,dis+maxn,inf);
    fill(e[0],e[0]+maxn*maxn,inf);
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        e[a][b]=e[b][a]=c;
    }
    prim();
    return 0;
}