题目描述
发展采矿业当然首先得有矿井,小 FF 花了上次探险获得的千分之一的财富请人在岛上挖了 n 口矿井,但他似乎忘记考虑的矿井供电问题……
为了保证电力的供应,小 FF 想到了两种办法:
在这一口矿井上建立一个发电站,费用为 v(发电站的输出功率可以供给任意多个矿井)。
将这口矿井与另外的已经有电力供应的矿井之间建立电网,费用为 p。
小 FF 希望身为「NewBe_One」计划首席工程师的你帮他想出一个保证所有矿井电力供应的最小花费。
输入格式
第一行一个整数 n,表示矿井总数。
第 2~n+1 行,每行一个整数,第 i 个数 vi 表示在第 i 口矿井上建立发电站的费用。
接下来为一个 n*n 的矩阵 p,其中 pi,j 表示在第 i 口矿井和第 j 口矿井之间建立电网的费用(数据保证有 pi,j=pj,i,且 pi,i=0)。
输出格式
输出仅一个整数,表示让所有矿井获得充足电能的最小花费。
样例
输入
4
5
4
4
3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0
输出
9
小 FF 可以选择在 号矿井建立发电站然后把所有矿井都不其建立电网,总花费是 3+2+2+2=9。
数据范围与提示
对于 30% 的数据:1<=n<=50;
对于 100% 的数据:1<=n<=300,0<=vi,pi,j<=10^5。
思路
将在每个矿井上安装的发电站设成第n+1条边,prim求最短距离
#include<bits/stdc++.h>
using namespace std;
const int N=333;
int n,m,dis[N][N];
int main()
{
cin>>n;
memset(dis,0,sizeof(dis));
for(int i=1;i<=n;i++) {
cin>>dis[i][n+1];
dis[n+1][i]=dis[i][n+1];
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>m;
dis[i][j]=m;
}
}
n++;
int book[N]={0},inf=0x3f3f3f;
int vis[N]={0},ans=0;
for(int i=1;i<=n;i++) vis[i]=dis[1][i];
book[1]=1;
vis[1]=0;
for(int i=1;i<=n;i++){
int MIN=inf,k=0;
for(int j=1;j<=n;j++){
if(!book[j]&&vis[j]<MIN){
MIN=vis[j];
k=j;
}
}
book[k]=1;
ans+=vis[k];
for(int j=1;j<=n;j++)
vis[j]=min(vis[j],dis[k][j]);
}
cout<<ans<<endl;
}