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.



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章