####Description
Zjr506很喜欢猫,某一天他突然心血来潮,想捕捉学校里活动的猫。
为了捕猫,Zjr506在校园中放置了N个木桩,当他见到有猫进入他的狩猎范围后,就会以迅雷不及掩耳的速度在一些木桩之间绕上藩篱以困住这些猫。
一段时间后,Zjr506在绕了M个藩篱后兴高采烈的离开了。作为正义的使者,Ztxz16不忍心看到这些猫受到折磨,于是决定拆除一些藩篱让所有的猫都逃出去。因为Zjr506的巧妙设计,藩篱不会在除木桩之外的地方相交。这些藩篱构成了一些封闭的区域,每一个区域中都有一只猫。
因为Zjr506制造这些藩篱也不容易,所以Ztxz16希望拆除的藩篱总长度尽量小,现在他希望你告诉他最小的总长度。
####Input
第一行两个数 n,m ( 2<=n<=10000 , 1<=m<=50000 )
接下来 n 行 , 每行两个整数 xi,yi, 代表第 i 个木桩的坐标 ( − 10000 ≤ xi, yi ≤ 10000).
接下来 m 行,每行两个整数 pi,qi (1 ≤ pj, qj ≤ N) , 代表木桩 pi 与木桩 qi 之间有一个藩篱。
####Output
输出一个实数代表答案,当答案与标准答案差的绝对值不超过0.001时认为它是正确的。
####Sample Input
8 8
0 0
3 0
3 3
0 3
1 1
1 2
2 2
2 1
1 2
2 3
3 4
4 1
5 6
6 7
7 8
8 5
####Sample Output
4.000000000
####Data Constraint
对于20%的数据:
N , M <= 30
对于30%的数据:
N, M <= 300
对于100%的数据:
N <= 10000, M <= 50000
###题解
首先,看到题目以为是什么暴力搜索或是什么玄学的东东,但是转念一看,发现是要删边,再认真看看,原来是给出很多条边,然后去掉比较小的边,让整个图没有环。
正着去看,发现去掉小边比较麻烦,那么就反着来看。
于是本题就变成了求最大生成树。(很类似)
我们怎么做呢?
首先先排个序,然后一条一条边加入图中,若是当前边加入了之后就出现环,那么就不加入。答案就把这条边的距离加上。用题目的话来说就是把这条栏杆给去掉。
正确性?
因为当前边是当前环(连上了之后)最小的边,去掉其他的边不是更优的,所以去掉当前边是最优解。
那么如何判断是一个环?就直接用一个简单的并查集即可。
Code:
type
new=record
x:longint;
y:longint;
long:extended;
end;
var
f:array[1..100001] of longint;
a:array[0..100001] of new;
e:array[0..100001,1..2] of longint;
i,j,k,n,m,x,y,c:longint;
ans:extended;
procedure qsort(l,r:longint);
var
x,y:longint;
m:extended;
begin
x:=l;
y:=r;
m:=a[(l+r) div 2].long;
repeat
while a[x].long>m do inc(x);
while a[y].long<m do dec(y);
if x<=y then
begin
a[0]:=a[x];
a[x]:=a[y];
a[y]:=a[0];
inc(x);
dec(y);
end;
until x>y;
if l<y then qsort(l,y);
if r>x then qsort(x,r);
end;
function fu(z:longint):longint;
var
x,y:longint;
begin
y:=z;
while y<>f[y] do y:=f[y];
while z<>y do
begin
x:=f[z];
f[z]:=y;
z:=x;
end;
exit(y);
end;
begin
readln(n,m);
for i:=1 to n do
begin
readln(x,y);
e[i,1]:=x;
e[i,2]:=y;
end;
for i:=1 to m do
begin
readln(x,y);
a[i].x:=x;a[i].y:=y;
a[i].long:=sqrt(sqr(e[x,1]-e[y,1])+sqr(e[x,2]-e[y,2]));
end;
qsort(1,m);
for i:=1 to n do f[i]:=i;
ans:=0;
for i:=1 to m do
begin
j:=fu(a[i].x);
k:=fu(a[i].y);
if j<>k then
begin
f[j]:=k;
end
else
begin
ans:=ans+a[i].long;
end;
end;
writeln(ans:0:9);
end.