Usaco2009 gold 修建道路

来源:互联网 发布:王师就剩一个连 知乎 编辑:程序博客网 时间:2024/05/16 20:30

修建道路

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 11 13 12 34 31 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.

0 0
原创粉丝点击