JZOJsenior4740.【雅礼联考GDOI2017模拟9.2】Zjr506的捕猫计划

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

思路:
我们先换个思路来理解这道题目
YY一下一个封闭牛圈,木桩看成点,篱笆看成边,既然他是要封闭的,那么他肯定是一个环,对吧?
现在我们去掉任意一条边,他就不是一个环而是一棵树了
题目要保证一定保证整幅图没有环(有环里面就有猫),我们就不能让这个图出现环
那这道题就是一道裸的MST……

只不过和MST不同的是,这里要删掉的边最短,所以是求最大生成树而已
用kruskal搞最大生成树,判断环用并查集
如果当前边连接x和y,而x的祖先和y的祖先相同,那再连就会有环出现,当前边不选
比较简单,那就AC吧

代码:

var
        x,y,father:array[0..10000]of longint;
        a:array[0..50000]of
        record
                dis:extended;
                x,y:longint;
        end;
        n,m,i,j,k,l,r:longint;
        ans:extended;
procedure qsort(l,r:longint);
var
        i,j:longint;
        mid:extended;
begin
        i:=l;
        j:=r;
        mid:=a[(l+r)shr 1].dis;
        repeat
                while a[i].dis>mid do inc(i);
                while a[j].dis<mid do dec(j);
                if i<=j then
                begin
                        a[0]:=a[i];
                        a[i]:=a[j];
                        a[j]:=a[0];
                        inc(i);
                        dec(j);
                end;
        until i>j;
        if l<j then qsort(l,j);
        if i<r then qsort(i,r);
end;
function getfather(x:longint):longint;
begin
        if father[x]=x then exit(x);
        father[x]:=getfather(father[x]);
        exit(father[x]);
end;
begin
        readln(n,m);
        for i:=1 to n do readln(x[i],y[i]);
        for i:=1 to m do
        begin
                readln(l,r);
                a[i].x:=l;
                a[i].y:=r;
                a[i].dis:=sqrt(sqr(x[l]-x[r])+sqr(y[l]-y[r]));
        end;
        qsort(1,m);
        for i:=1 to n do father[i]:=i;
        for i:=1 to m do
        begin
                j:=getfather(a[i].x);
                k:=getfather(a[i].y);
                if j<>k then father[j]:=k
                else ans:=ans+a[i].dis;
        end;
        writeln(ans:0:9);
end.
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值