洛谷P1550 [USACO08OCT]打井Watering Hole(kruscal) 题解

题目来源:

点击打开链接

题目描述:

题目背景

John的农场缺水了!!!

题目描述

Farmer John has decided to bring water to his N (1 <= N <= 300) pastures which are conveniently numbered 1..N. He may bring water to a pasture either by building a well in that pasture or connecting the pasture via a pipe to another pasture which already has water.

Digging a well in pasture i costs W_i (1 <= W_i <= 100,000).

Connecting pastures i and j with a pipe costs P_ij (1 <= P_ij <= 100,000; P_ij = P_ji; P_ii=0).

Determine the minimum amount Farmer John will have to pay to water all of his pastures.

POINTS: 400

农民John 决定将水引入到他的n(1<=n<=300)个牧场。他准备通过挖若

干井,并在各块田中修筑水道来连通各块田地以供水。在第i 号田中挖一口井需要花费W_i(1<=W_i<=100,000)元。连接i 号田与j 号田需要P_ij (1 <= P_ij <= 100,000 , P_ji=P_ij)元。

请求出农民John 需要为连通整个牧场的每一块田地所需要的钱数。

输入输出格式

输入格式:

第1 行为一个整数n。

第2 到n+1 行每行一个整数,从上到下分别为W_1 到W_n。

第n+2 到2n+1 行为一个矩阵,表示需要的经费(P_ij)。

输出格式:

只有一行,为一个整数,表示所需要的钱数。

输入输出样例

输入样例#1:  复制
4
5
4
4
3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0
输出样例#1:  复制
9







说明

John等着用水,你只有1s时间!!!


解题思路:

       这题是一个接近最小生成树的裸题,关键是要考虑打井的问题,因为农田之中的建的水道,与丼无关,关键是选择哪些丼要打,一开始我是单纯的认为只要将农田之间算出最小生成树在加上最便宜的打井费就行,当然就只有50了,因为有可能农田之间的费用很高,而打井便宜,就不止打一个丼了。正解应该是多设置一个点0,每一个打井,就是从0到i号丼建一条边,边权就是费用,那么题目就是求0-n个点最小生成树的值

代码:

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
struct newt{
	int	from,to,cost;
}edge[100000];
int father[10000];
bool cmp(newt a,newt b)
{
	return a.cost<b.cost;
}
int n;
void init()
{
	for(int i=0;i<=n;i++)
	father[i]=i;
}
int fi(int x)
{
	if(father[x]==x)return x;
	else return father[x]=fi(father[x]);
}
bool same(int x,int y)
{
	if(fi(x)==fi(y))return 1;
	return 0;
}
void Union(int x,int y)
{
	int u=fi(x),v=fi(y);
	if(u==v)return ;
	father[u]=v;
}
int jg[10000];
int main()
{
	int t=1;
	cin>>n;int Min=1e9;init();
	for(int i=1;i<=n;i++)
	{
		cin>>jg[i];
		edge[t].from=0;edge[t].to=i;edge[t++].cost=jg[i];
	}
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	{
		int a;
		cin>>a;
		edge[t].from=i;edge[t].to=j;edge[t++].cost=a;
	}
	sort(edge+1,edge+t,cmp);
	int ans=0;
	for(int i=1;i<t;i++)
	{
		if(!same(edge[i].from,edge[i].to)){
			ans+=edge[i].cost;
			Union(edge[i].from,edge[i].to);
		}
	}
	cout<<ans<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40400202/article/details/81048506