1. 程式人生 > >HihoCoder 1097 Prim算法

HihoCoder 1097 Prim算法

str 時間 連通 滿足 algorithm coder log 接下來 head

1097 : 最小生成樹一·Prim算法

時間限制:10000ms 單點時限:1000ms 內存限制:256MB

描述

最近,小Hi很喜歡玩的一款遊戲模擬城市開放出了新Mod,在這個Mod中,玩家可以擁有不止一個城市了!

但是,問題也接踵而來——小Hi現在手上擁有N座城市,且已知這N座城市中任意兩座城市之間建造道路所需要的費用,小Hi希望知道,最少花費多少就可以使得任意兩座城市都可以通過所建造的道路互相到達(假設有A、B、C三座城市,只需要在AB之間和BC之間建造道路,那麽AC之間也是可以通過這兩條道路連通的)。

提示:不知道為什麽Prim算法和Dijstra算法很像呢Σ(っ °Д °;)っ 。

輸入

每個測試點(輸入文件)有且僅有一組測試數據。

在一組測試數據中:

第1行為1個整數N,表示小Hi擁有的城市數量。

接下來的N行,為一個N*N的矩陣A,描述任意兩座城市之間建造道路所需要的費用,其中第i行第j個數為Aij,表示第i座城市和第j座城市之間建造道路所需要的費用。

對於100%的數據,滿足N<=10^3,對於任意i,滿足Aii=0,對於任意i, j滿足Aij=Aji, 0<Aij<10^4.

輸出

對於每組測試數據,輸出1個整數Ans,表示為了使任意兩座城市都可以通過所建造的道路互相到達至少需要的建造費用。

樣例輸入
5
0 1005 6963 392 1182 
1005 0 1599 4213 1451 
6963 1599 0 9780 2789 
392 4213 9780 0 5236 
1182 1451 2789 5236 0 
樣例輸出
4178

對於一棵最小生成樹T——如果edge(i, j)在其中,那麽該結論就已經得到了證明。所以我們考慮的是e(i, j)不在其中的情況。而i和j之間肯定會通過某條路徑連通(因為是樹不是森林),不妨假設為i-p1-p2-...-pk-j。”

“嗯嗯,然後呢?”

“那麽,如果我將(i, p1)這條邊刪去,添加上(i, j)這條邊,那麽這還是一棵生成樹麽?”小Hi問道。

“點沒有發生變化,邊集仍然是圖G的子集,那麽只需要看還是不是一個棵樹了——所有點之間仍然連通,而且沒有環(添加邊(1, i)後僅有一個環i-p1-p2-...-pk-j-i,但是(i, p1)卻被刪去了)!所以這還是一棵樹,也就是說……這樣改動之後仍然是一棵生成樹

prim思想基於dijistra

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int inf=1e9;
const int maxn=1010;
int dis[maxn],ans;
int a[maxn][maxn];
int used[maxn],n;
void _prim()
{
    int i,j,Min,pos;
    for(i=1;i<=n;i++) dis[i]=inf;
    dis[1]=0;
    _prim();
    for(i=1;i<=n;i++){
         Min=1e9;
         for(j=1;j<=n;j++){
            if(!used[j]&&dis[j]<Min){
               Min=dis[j];pos=j;
             }
         }
         used[pos]=1;
         ans+=dis[pos];
         for(j=1;j<=n;j++)
         if(dis[j]>a[pos][j]) dis[j]=a[pos][j];
    }
}
int main()
{    
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++) scanf("%d",&a[i][j]);
     
    printf("%d\n",ans);
    return 0;
}

HihoCoder 1097 Prim算法