新的开始(朴素版prim算法)
作者:互联网
题目:新的开始
题目链接:https://ac.nowcoder.com/acm/problem/50362
题意:有n个矿井,有两种方法可以保证矿井的电力供应:
- 在该矿井上建立发电站,费用为v。
- 将该矿井与已有电力供应的矿井间建立电网,费用为p。
求保证所有矿井都有电力供应的最小花费。
输入描述:
第一行输入矿井个数n(1 <= n <= 300)。
接下来n行,第i个数vi表示在第i个矿井上建立发电站的费用。
接下来一个n * n的矩阵p,表示每两个矿井间建立电网的费用。
样例输入:
4
5
4
4
3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0
样例输出:
9
样例解释:在4号矿井建立发电站,在1,4之间,1,2之间,1,3之间建立电网,费用为3 + 2 + 2 + 2 = 9。
题目分析:最小生成树,可以使用prim算法求解。
解题步骤:
- 建立一个虚点0,在虚点0和所有矿井之间连接一条vi的边,这样虚点0到矿井i的距离就可以替代在矿井i上建立发电站的费用。
- 以虚点0为起点,做prim算法即可得到答案。
AC代码:
#include<iostream>
using namespace std;
const int N = 310, inf = 1e9;
int g[N][N], dis[N], b[N], n;
int prim(){
for(int i = 1;i <= n;i++) dis[i] = inf;
dis[0] = 0;
int res = 0;
for(int i = 0;i <= n;i++){
int t = -1;
for(int j = 0;j <= n;j++){
if(b[j] == 0 && (t == -1 || dis[j] < dis[t])) t = j;
}
res += dis[t];
b[t] = 1;
for(int j = 0;j <= n;j++) dis[j] = min(dis[j], g[t][j]);
}
return res;
}
void solve(){
scanf("%d", &n);
for(int i = 1;i <= n;i++) scanf("%d", &g[0][i]);
for(int i = 1;i <= n;i++){
for(int j = 1;j <= n;j++){
scanf("%d", &g[i][j]);
}
}
printf("%d\n", prim());
}
int main(void){
solve();
return 0;
}
时间复杂度:O(n ^ 2)。
空间复杂度:O(n ^ 2)。
标签:prim,int,矿井,发电站,算法,虚点,朴素,dis 来源: https://www.cnblogs.com/www-cnblogs-com-lixuanta/p/15579841.html