题目描述
发展采矿业固然首先得有矿井,小 FF 花了上次探险得到的千分之一的财富请人在岛上挖了 nnn 口矿井,但他彷佛忘记考虑的矿井供电问题……html
为了保证电力的供应,小 FF 想到了两种办法:ios
- 在这一口矿井上创建一个发电站,费用为 vvv(发电站的输出功率能够供给任意多个矿井)。
- 将这口矿井与另外的已经有电力供应的矿井之间创建电网,费用为 ppp。
小 FF 但愿身为「NewBe_One」计划首席工程师的你帮他想出一个保证全部矿井电力供应的最小花费。post
输入格式ui
第一行一个整数 nnn,表示矿井总数。spa
第 2∼n+12\sim n+12∼n+1 行,每行一个整数,第 iii 个数 viv_ivi 表示在第 iii 口矿井上创建发电站的费用。code
接下来为一个 n×nn\times nn×n 的矩阵 ppp,其中 pi,jp_{i,j}pi,j 表示在第 iii 口矿井和第 jjj 口矿井之间创建电网的费用(数据保证有pi,j=pj,ip_{i,j}=p_{j,i}pi,j=pj,i,且 pi,i=0p_{i,i}=0pi,i=0)。htm
输出格式
输出仅一个整数,表示让全部矿井得到充足电能的最小花费。blog
思路:感受这题创建超级源点的方法挺巧妙的,之前没有碰到过,因此记录一下。这道题若是吧超级源点到每一个矿井连边,边权为建发电站的费用,能够看出,咱们须要的是最小的边权和,这就成了最小生成树的模型,n只有300,跑一边prim就好了。ip
代码:string
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #define ll long long int using namespace std; const int INF=0x3f3f3f3f; int n,val[305],p[305][305],ans,col[305],dis[305]; void prim(){ for(int i=1;i<=n-1;i++) dis[i]=p[n][i]; p[n][n]=INF; dis[n]=0;col[n]=1; for(register int i=1;i<=n-1;i++){ int minn=INF,k; for(int j=1;j<=n;j++) if(!col[j]&&minn>dis[j]){ minn=dis[j]; k=j; } ans+=dis[k]; col[k]=1; for(int j=1;j<=n;j++) dis[j]=min(dis[j],p[k][j]); } } int main(){ scanf("%d",&n); n++; for(int i=1;i<=n-1;i++){ scanf("%d",&p[n][i]); p[i][n]=p[n][i]; } for(int i=1;i<=n-1;i++) for(int j=1;j<=n-1;j++) scanf("%d",&p[i][j]); for(int i=1;i<=n-1;i++){ p[i][i]=INF; dis[i]=INF; } prim(); printf("%d",ans); return 0; }