洛谷P1550 [USACO08OCT]打井Watering Hole

题目背景

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时间!!!

————————————————————————

这道题有个非常秒的转换 就是新建一个S作为河水

把所有的村庄和S连边 代价是打井的费用

然后就变成了一道最小生成树了

#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int M=507;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
    return ans*f;
}
int n,S,f[M],x;
LL ans;
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
struct node{int to,from,next,w;}e[M*M];
bool cmp(node a,node b){return a.w<b.w;}
int first[M],cnt,sum;
void ins(int a,int b,int w){cnt++; e[cnt].from=a; e[cnt].to=b; e[cnt].next=first[a]; e[cnt].w=w; first[a]=cnt;}
int main()
{
    n=read(); S=n+1;
    for(int i=1;i<=S;i++) f[i]=i;
    for(int i=1;i<=n;i++) x=read(),ins(S,i,x);
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++){
         x=read();
         if(j<i) ins(i,j,x);
     }
    sort(e+1,e+1+cnt,cmp);
    for(int i=1;i<=cnt;i++){
        int x=find(e[i].from),y=find(e[i].to);
        if(x==y) continue;
        f[y]=x; ans+=(LL)e[i].w;
        sum++; if(sum==S) break;
    }printf("%lld
",ans);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/lyzuikeai/p/7283687.html