【JZOJ】给水(water)

这篇博客探讨了一个图论问题,即如何在给定的费用条件下,通过立井和联通不同地块来确保每块地都有水源,从而达到最低成本。文章提供了输入输出样例,并建议使用Prim算法来求解这个问题,通过建立特殊节点并运行最小生成树算法找到最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DescriptionDescriptionDescription

nnn块地,可以花费w[i]w[i]w[i]元在第iii块地上立井,也可以花费p[i][j]p[i][j]p[i][j]iii地和jjj地联通
问最少花费多少钱才可以使得每块地都有水

InputInputInput

第一行,一个整数N
第2到N+1行,第i+1行输入W_i
第N+2到2N+1行,每行N个空格隔开的整数,表示P_ij

OutputOutputOutput

输出最少花费。

SampleSampleSample InputInputInput

4
5
4
4
3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0

SampleSampleSample OutputOutputOutput

9

HintHintHint

【样例解释】
FJ可以在草地4建井,并把草地2,3,4与草地1之间建立管道,花费为3+2+2+2=9

TrainTrainTrain ofofof ThoughtThoughtThought

可以建立一个点e,将e点和每一个点连接,其中的费用就是连接的点上立井的费用
然后跑一边遍primprimprim(最小生成树)就可以了

CodeCodeCode

#include<cstdio>
#include<cstring>
using namespace std;
bool b[305];
int ans,sum[305],p[305][305],w[305],n;
int main()
{
//	freopen("water.in","r",stdin);
//	freopen("water.out","w",stdout);
	scanf("%d",&n);
	for (int i=1; i<=n; ++i)
	  	scanf("%d",&w[i]);
	for (int i=1; i<=n; ++i)
	 for (int j=1; j<=n; ++j) 
	    scanf("%d",&p[i][j]);
	int e=n+1;
	for (int i=1; i<=n; ++i)
	 p[e][i]=p[i][e]=w[i];//连边
	memset(sum,0x7f,sizeof(sum));
	sum[1]=0;
	for (int i=1; i<=e; ++i)
	 {
	 	int u=0; 
	 	for (int j=1; j<=e; ++j)
	 	 if (sum[j]<sum[u] && !b[j]) u=j;//找出最小的点
	 	ans+=sum[u]; b[u]=true;
		for (int j=1; j<=e; ++j)
		 if (u!=j && p[u][j]<sum[j]) sum[j]=p[u][j]; //更新数值
	 }
	printf("%d",ans); 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值