Usaco2009 gold 修建道路

修建道路

Description

Farmer John最近得到了一些新的農場,他想新修一些道路使得他的所有農場可以經過原有的或是新修的道路互達(也就是說,從任一個農場都可以經過一些首尾相連道路到達剩下的所有農場)。有些農場之間原本就有道路相連。所有N(1 <= N <= 1,000)個農場(用1..N順次編號)在地圖上都表示爲座標爲(X_i, Y_i)的點(0 <= X_i <= 1,000,000;0 <= Y_i <= 1,000,000),兩個農場間道路的長度自然就是代表它們的點之間的距離。現在Farmer John也告訴了你農場間原有的M(1 <= M <= 1,000)條路分別連接了哪兩個農場,他希望你計算一下,爲了使得所有農場連通,他所需建造道路的最小總長是多少。

Input

* 第1行: 2個用空格隔開的整數:N 和 M
* 第2..N+1行: 第i+1行爲2個用空格隔開的整數:X_i、Y_i
* 第N+2..N+M+2行: 每行用2個以空格隔開的整數i、j描述了一條已有的道路,這條道路連接了農場i和農場j

Output

* 第1行: 輸出使所有農場連通所需建設道路的最小總長,保留2位小數,不必做 任何額外的取整操作。爲了避免精度誤差,計算農場間距離及答案時請使用64位實型變量


Sample Input

4 1

1 1

3 1

2 3

4 3

1 4

Sample Output

4.00

Hint

樣例說明:
FJ選擇在農場1和農場2間建一條長度爲2.00的道路,在農場3和農場4間建一條長度爲2.00的道路。這樣,所建道路的總長爲4.00,並且這是所有方案中道路總長最小的一種。

題解:
很明顯是最小生成樹,,,,,,,

參考程序:
var     n,m,i,j,x,y,lenb,t1,t2:longint;
        a:array[1..1000,1..2]of extended;
        b:array[0..1600000,1..2]of longint;
        fb:array[0..1600000]of extended;
        c:array[1..1000]of longint;
        ans:extended;
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:longint;
        mid:extended;
begin
        i:=l;j:=r;
        mid:=fb[(l+r)div 2];
        repeat
                while fb[i]<mid do inc(i);
                while fb[j]>mid do dec(j);
                if i<=j then
                begin
                        b[0]:=b[i];
                        b[i]:=b[j];
                        b[j]:=b[0];
                        fb[0]:=fb[i];
                        fb[i]:=fb[j];
                        fb[j]:=fb[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 m do
        begin
                readln(x,y);
                inc(lenb);
                b[lenb,1]:=x;
                b[lenb,2]:=y;
                fb[lenb]:=0;
        end;
        for i:=1 to n do
                for j:=1 to n do
                begin
                        if i=j then continue;
                        inc(lenb);
                        b[lenb,1]:=i;
                        b[lenb,2]:=j;
                        fb[lenb]:=sqrt((a[i,1]-a[j,1])*(a[i,1]-a[j,1])+(a[i,2]-a[j,2])*(a[i,2]-a[j,2]));
                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+fb[i];
                end;
        end;
        writeln(ans:0:2);
end.

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