(纪中)1930. 灌溉农田(irrigation)【最小生成树】

67 篇文章 0 订阅

*(File IO): input:irrigation.in output:irrigation.out
时间限制: 1000 ms 空间限制: 128000 KB 具体限制


题目描述
由于最近缺少降雨,农夫约翰决定在他的N块农田之间建立一个供水管网。每块的位置可以用一个二维坐标来表示 ( x i , y i ) (xi,yi) xi,yi,在第i块地和第j块地之间修建一个管道的话,代价是 ( x i − x j ) 2 + ( y i − y j ) 2 (xi - xj)^2 + (yi - yj)^2 (xixj)2+(yiyj)2。农夫约翰想要建立一个花费代价最小的供水管网,使得他所有的地都能被连接在一起(使得水能够通过一系列的管道流到各个田地里去)。不幸的是,建造管道的人拒绝建造花费代价小于C的单条管道。请帮助约翰计算最少需要花费多少代价,才能建成这个供水管网。


输入
第一行是两个正整数 N N N C C C
2 2 2行到第 N + 1 N+1 N+1行,每行两个整数,表示 x i xi xi y i yi yi

输出
输出建立供水管网的最小代价,如果不能建立供水管网,就输出 − 1 -1 1


样例输入
3 11
0 2
5 0
4 3

样例输出
46


数据范围限制
1 < = N < = 2000 , 0 < = x i , y i < = 1000 1<=N<=2000,0<=xi,yi<=1000 1<=N<=2000,0<=xi,yi<=1000


提示
样例中,约翰不能在 ( 4 , 3 ) (4,3) 4,3 ( 5 , 0 ) (5,0) 5,0之间建立管道,因为这个管道的代价是 10 10 10。因此,他只能在 ( 0 , 2 ) (0,2) 0,2 ( 5 , 0 ) (5,0) 5,0之间修建一条管道,花费是 29 29 29,在 ( 0 , 2 ) (0,2) 0,2 ( 4 , 3 ) (4,3) 4,3之间修建一条管道,花费是 17 17 17,所以总的最小花费是 29 + 17 = 46 29+17=46 29+17=46


解题思路
这道题就是一道最小生成树,可以采用普里姆算法.


代码

#include<bits/stdc++.h>
using namespace std;
int n,c,x[2020],y[2020],a[2020][2020],v[2020],b[2020],minn,k,ans;
int main()
{
	freopen("irrigation.in","r",stdin);
    freopen("irrigation.out","w",stdout);
    scanf("%d%d",&n,&c);
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            a[i][j]=999999999;
    for(int i=1; i<=n; i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        for(int j=1; j<=i-1; j++)
            if((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])>=c)
                a[i][j]=a[j][i]=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
    }
    v[1]=1;
    for(int i=2; i<=n; i++)
        b[i]=a[1][i];
    for(int j=1; j<=n-1; j++)
    {
        minn=999999998;
        for(int j=1; j<=n; j++)
            if(v[j]==0&&b[j]<=minn)
            {
                minn=b[j];
                k=j;
            }
        v[k]=1;
        ans+=b[k];
        for(int j=1; j<=n; j++)
            if(v[j]==0&&a[j][k]<=b[j])
                b[j]=a[j][k];
    }
    for(int i=1; i<=n; i++)
        if(!v[i])
        {
            printf("-1");
            return 0;
        }
    printf("%d",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值