题目描述
Farmer John 的农场缺水了。
他决定将水引入到他的 n 个农场。他准备通过挖若干井,并在各块田中修筑水道来连通各块田地以供水。在第 i 号田中挖一口井需要花费 Wi 元。连接 i 号田与 j 号田需要 Pi,j(Pj,i=Pi,j)元。
请求出 FJ 需要为使所有农场都与有水的农场相连或拥有水井所需要的最少钱数。
输入格式
第一行为一个整数 n。
接下来 n 行,每行一个整数 Wi。
接下来 n 行,每行 n 个整数,第 i 行的第 j 个数表示连接 i 号田和 j 号田需要的费用 Pi,j。
输出格式
输出最小开销。
输入输出样例
输入 #1
4 5 4 4 3 0 2 2 2 2 0 3 3 2 3 0 4 2 3 4 0
输出 #1
9
说明/提示
对于 100% 的数据,1≤n≤300,1≤Wi≤10^5,0≤Pi,j≤10^5。
解题思路
最小生成树问题,这题不一样的就是可能存在连通两个田的成本大于挖井的成本,只需要在邻接矩阵输入的时候取两者较小值然后就不会存在连通两个田的成本大于挖井的成本的情况,这样就只需要挖一个井,操作起来相对简单。
AC代码
#include<stdio.h>
int n, a[301][301], w[301], k = 0, dis[301], book[301];
int main()
{
int i, j, min = 1e9;
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
scanf("%d", &w[i]);
if (min > w[i])//取所有田中挖井成本最小的田
{
min = w[i]; k = i;
}
}
for(i=1;i<=n;i++)//邻接矩阵
for (j = 1; j <= n; j++)
{
scanf("%d", &a[i][j]);
if (a[i][j] > w[j])
a[i][j] = w[j];
}
for (i = 1; i <= n; i++)//dis数组初始化
dis[i] = a[k][i];
book[k] = 1;
int sum = min;
//普里姆算法核心代码
for (i = 1; i < n; i++)//建立n-1条边
{
min = 1e9;
for (j = 1; j <= n; j++)
{
if (book[j] == 0 && min > dis[j])
{
k = j; min = dis[j];
}
}
book[k] = 1; sum += min;//标记+统计和
for (j = 1; j <= n; j++)//松弛
{
if (dis[j] > a[k][j])
dis[j] = a[k][j];
}
}
printf("%d", sum);//输出答案
return 0;
}