最小生成树:新的开始
Posted 719666a
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最小生成树:新的开始相关的知识,希望对你有一定的参考价值。
题目描述
发展采矿业当然首先得有矿井,小 FF 花了上次探险获得的千分之一的财富请人在岛上挖了 nnn 口矿井,但他似乎忘记考虑的矿井供电问题……
为了保证电力的供应,小 FF 想到了两种办法:
- 在这一口矿井上建立一个发电站,费用为 vvv(发电站的输出功率可以供给任意多个矿井)。
- 将这口矿井与另外的已经有电力供应的矿井之间建立电网,费用为 ppp。
小 FF 希望身为「NewBe_One」计划首席工程师的你帮他想出一个保证所有矿井电力供应的最小花费。
输入格式
第一行一个整数 nnn,表示矿井总数。
第 2~n+12sim n+12~n+1 行,每行一个整数,第 iii 个数 viv_iv?i?? 表示在第 iii 口矿井上建立发电站的费用。
接下来为一个 n×nn imes nn×n 的矩阵 ppp,其中 pi,jp_{i,j}p?i,j?? 表示在第 iii 口矿井和第 jjj 口矿井之间建立电网的费用(数据保证有pi,j=pj,ip_{i,j}=p_{j,i}p?i,j??=p?j,i??,且 pi,i=0p_{i,i}=0p?i,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 可以选择在 444 号矿井建立发电站然后把所有矿井都不其建立电网,总花费是 3+2+2+2=93+2+2+2=93+2+2+2=9。
分析:这道题原来用的克鲁斯卡尔算法(最小生成树+最小v[i]),在LOJ上最多得了50分。其实它可能出现一个矿井修电网还不如修电站的情况,故改用Prim算法
#include<bits/stdc++.h> using namespace std; int a[1000][1000],v[1000]; int dis[10000]; bool book[10000]; #define inf 1e12; int main() { int n; cin>>n; for(int i=1;i<=n;i++) { cin>>v[i]; a[i][n+1]=v[i]; a[n+1][i]=v[i]; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>a[i][j]; memset(book,0,sizeof book); for(int k=1;k<=n+1;k++) { dis[k]=a[1][k]; } book[1]=1; int ans=0; for(int k=1;k<=n;k++) { long long mins=inf; int minj; for(int j=1;j<=n+1;j++) { if(!book[j]&&dis[j]<mins) { mins=dis[j]; minj=j; } } book[minj]=1; ans+=dis[minj]; for(int j=1;j<=n+1;j++) if(book[j]==0&&dis[j]>a[minj][j]) dis[j]=a[minj][j]; } cout<<ans; }
以上是关于最小生成树:新的开始的主要内容,如果未能解决你的问题,请参考以下文章