2014.3 USACO月赛T1 Watering the Fields

Watering the Fields 

题目描述
由于缺少雨水,FJ 想要建造一个在他的N(1 N 2000)块田之间送水的灌溉系统。
每块田地i 由一个二维平面上独一无二的点(xi; yi) 描述,这里有0 <= xi; yi <=1000。在两块田地i 和j 之间建造水管的费用等于它们之间欧几里得距离的平方:(xi-xj)^2+(yi-yj)^2
FJ 希望建造一个连接所有田地并且花费最小的管道系统——满足从任意田地出发,水可以通过一系列管道到达另外的任意一块田地。
不幸的是,帮助FJ 安装灌溉系统的承包商拒绝安装任何花费(欧几里得长度平方)小于C(1 C 1; 000; 000)的管道。
请帮助FJ 计算他最少需要为连接他所有田地的管道网络支付多少钱。
 
输入格式
第一行:整数N 和C。
第2 至N + 1 行:第i 行包含整数xi 和yi。
输出格式
输出单独一行一个整数——连接所有田地的管道网络的最小费用,或者当满足条件的网络不可能建造时输出-1。
输入样例
3 11
0 2
5 0
4 3
输出样例
46
样例解释:
有三块田地,分别在坐标(0; 2); (5; 0) 和(4; 3)。承包商将只会安装费用不少于11 的管道。
FJ 不能建造连接分别在(4; 3) 和(5; 0) 的田地的管道,因为它的费用只有10。
故他只得建造连接(0; 2) 和(5; 0) 且费用为29 的管道,以及连接(0; 2) 和(4; 3)且费用为17 的管道。
 
数据范围
对于20% 的数据,有N <= 10。
对于30% 的数据,有N <= 100。
对于40% 的数据,有N <= 200。

题解:
先把每两个点之间建立边,然后将边小于C的砍掉,再用最小生成树算法

参考程序:
var     n,m,i,j,x,y,bz,lenb,ans,t1,t2:longint;
        a:array[1..2000,1..2]of longint;
        f:array[1..2000,1..2000]of longint;
        b:array[0..4000000,1..3]of longint;
        c:array[1..2000]of longint;
function father(x:longint):longint;
begin
        if c[x]=x then exit(x) else exit(father(c[x]));
end;
procedure kuaipai(l,r:longint);
var     i,j,mid:longint;
begin
        i:=l;j:=r;
        mid:=b[(l+r)div 2,3];
        repeat
                while b[i,3]<mid do inc(i);
                while b[j,3]>mid do dec(j);
                if i<=j then
                begin
                        b[0]:=b[i];
                        b[i]:=b[j];
                        b[j]:=b[0];
                        inc(i);
                        dec(j);
                end;
        until i>j;
        if l<j then kuaipai(l,j);
        if i<r then kuaipai(i,r)
end;
begin
        readln(n,m);
        for i:=1 to n do
        begin
                readln(x,y);
                a[i,1]:=x;
                a[i,2]:=y;
        end;
        for i:=1 to n do
        begin
                bz:=0;
                for j:=1 to n do
                        if (a[i,1]-a[j,1])*(a[i,1]-a[j,1])+(a[i,2]-a[j,2])*(a[i,2]-a[j,2])>=m then
                        begin
                                f[i,j]:=(a[i,1]-a[j,1])*(a[i,1]-a[j,1])+(a[i,2]-a[j,2])*(a[i,2]-a[j,2]);
                                inc(lenb);
                                b[lenb,1]:=i;
                                b[lenb,2]:=j;
                                b[lenb,3]:=f[i,j];
                                bz:=1;
                        end;
                if bz=0 then
                begin
                        writeln(-1);
                        exit;
                end;
        end;
        kuaipai(1,lenb);
        for i:=1 to lenb do c[b[i,1]]:=b[i,1];
        for i:=1 to lenb do
        begin
                c[b[i,1]]:=father(b[i,1]);
                c[b[i,2]]:=father(b[i,2]);
                if c[b[i,1]]<>c[b[i,2]] then
                begin
                        c[c[b[i,2]]]:=c[b[i,1]];
                        ans:=ans+b[i,3];
                end;
        end;
        writeln(ans);
end.



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值