Java教程

新的开始(朴素版prim算法)

本文主要是介绍新的开始(朴素版prim算法),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

题目:新的开始

题目链接:https://ac.nowcoder.com/acm/problem/50362

题意:有n个矿井,有两种方法可以保证矿井的电力供应:

  1. 在该矿井上建立发电站,费用为v。
  2. 将该矿井与已有电力供应的矿井间建立电网,费用为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算法求解。

解题步骤:

  1. 建立一个虚点0,在虚点0和所有矿井之间连接一条vi的边,这样虚点0到矿井i的距离就可以替代在矿井i上建立发电站的费用。
  2. 以虚点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算法)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!