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

Description

Zjr506很喜欢猫,某一天他突然心血来潮,想捕捉学校里活动的猫。
为了捕猫,Zjr506在校园中放置了N个木桩,当他见到有猫进入他的狩猎范围后,就会以迅雷不及掩耳的速度在一些木桩之间绕上藩篱以困住这些猫。
一段时间后,Zjr506在绕了M个藩篱后兴高采烈的离开了。作为正义的使者,Ztxz16不忍心看到这些猫受到折磨,于是决定拆除一些藩篱让所有的猫都逃出去。因为Zjr506的巧妙设计,藩篱不会在除木桩之外的地方相交。这些藩篱构成了一些封闭的区域,每一个区域中都有一只猫。
因为Zjr506制造这些藩篱也不容易,所以Ztxz16希望拆除的藩篱总长度尽量小,现在他希望你告诉他最小的总长度。

Solution

第一想法就是对于每一个环都拆除一条最小边,但是发现可能拆除了一条边后,两个环合为一个,那么就要重新找环,效率不高,多数重复。再进一步思考,真正的模型应该是:对于每一个连通块,不断地删去最小的边,且不会使连通块分离。换一条思路,对于一个环来说,破除一条边,也就相当于保留最大的n-1条边,就是最大生成树,对于一幅图做最大生成树也能解决刚才的问题。

Code

var
    x,y,fa:array[1..10000] of longint;
    len:array[0..50000] of extended;
    u,v:array[0..50000] of longint;
    n,m,i,fu,fv:longint;
    ans:extended;
procedure qsort(l,r:longint);
var
    i,j:longint;
    mid:extended;
begin
    i:=l;j:=r;
    mid:=len[(i+j)div 2];
    repeat
        while len[i]>mid do inc(i);
        while mid>len[j] do dec(j);
        if i<=j then
        begin
            u[0]:=u[i];v[0]:=v[i];len[0]:=len[i];
            u[i]:=u[j];v[i]:=v[j];len[i]:=len[j];
            u[j]:=u[0];v[j]:=v[0];len[j]:=len[0];
            inc(i); dec(j);
        end;
    until i>j;
    if i<r then qsort(i,r);
    if l<j then qsort(l,j);
end;
function get(x:longint):longint;
begin
    if (fa[x]=0)or(fa[x]=x) then fa[x]:=x else fa[x]:=get(fa[x]);
    exit(fa[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(u[i],v[i]);
        len[i]:=sqrt(sqr(x[u[i]]-x[v[i]])+sqr(y[u[i]]-y[v[i]]));
        ans:=ans+len[i];
    end;
    qsort(1,m);
    for i:=1 to m do
    begin
        fu:=get(u[i]); fv:=get(v[i]);
        if fu=fv then continue;
        fa[fu]:=fv;
        ans:=ans-len[i];
    end;
    writeln(ans:0:9);
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值