洛谷P1550 [USACO08OCT]Watering Hole G

1、简明题意

要引水入 \(n\)个牧场,一开始每个牧场没水,可以挖井或铺管道,第 \(i\)个牧场挖井要 \(w[i]\)块钱,铺连接第 \(i\)\(j\)两个牧场的管道要 \(p[i][j]\)块钱,且 \(p[i][j]=p[j][i]\)。求把\(n\)个牧场全部变成有水的最小代价。

2、思路:

一开始还真的没思路TAT
最后经过多方询问,终于明白了这题怎么写。
先假设还有第 \(n+1\)个牧场,这个牧场很奇怪,自己就有水(水从天而降)
那么从这个牧场到第 \(i\)个牧场的距离便为 \(w[i]\)
最后跑一遍 \(n+1\)个点的最小生成树就行了。
就是最小生成树模板。

3、code:

kruscal版:

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
using namespace std;
const int N=305;
const int M=100005;
int ans=0;
struct node{
	int u,v,w;
}a[M];
int fa[N],n,ww[N],mapp[N][N];
int find(int x)
{
	return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x!=y)
	{
		fa[y]=x;
	}
}
bool cmp(node x,node y)
{
	return x.w<y.w;
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		fa[i]=i;
	}
	int cnt=0;
	for(int i=1;i<=n;i++)
	{
		cin>>ww[i];
		a[++cnt].u=i,a[cnt].v=n+1,a[cnt].w=ww[i];
	} 
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>mapp[i][j];
			if(i>j)
			{
				a[++cnt].u=i;
				a[cnt].v=j;
				a[cnt].w=mapp[i][j];
			}
		} 
	}
	sort(a+1,a+cnt+1,cmp);
	for(int i=1;i<=cnt;i++)
	{
		if(find(a[i].u)!=find(a[i].v))
		{
			merge(a[i].u,a[i].v);
			ans+=a[i].w;
		}
	} 
	cout<<ans;
    return 0;
}

posted @ 2020-04-11 21:18  panjx  阅读(215)  评论(0编辑  收藏  举报