• 2017.08.19【NOIP提高组】模拟赛B组 【雅礼联考GDOI2017模拟】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

    ###题解
    首先,看到题目以为是什么暴力搜索或是什么玄学的东东,但是转念一看,发现是要删边,再认真看看,原来是给出很多条边,然后去掉比较小的边,让整个图没有环。
    正着去看,发现去掉小边比较麻烦,那么就反着来看。
    于是本题就变成了求最大生成树。(很类似)
    我们怎么做呢?
    首先先排个序,然后一条一条边加入图中,若是当前边加入了之后就出现环,那么就不加入。答案就把这条边的距离加上。用题目的话来说就是把这条栏杆给去掉。
    正确性?
    因为当前边是当前环(连上了之后)最小的边,去掉其他的边不是更优的,所以去掉当前边是最优解。
    那么如何判断是一个环?就直接用一个简单的并查集即可。

    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.
    
    
    
    我活在这夜里。无论周围多么黑暗,我都要努力发光!我相信着,终有一天,我会在这深邃的夜里,造就一道最美的彩虹。
  • 相关阅读:
    软件工程第二次结对作业
    实验 6:OpenDaylight 实验——OpenDaylight 及 Postman 实现流表下发
    实验 5:OpenFlow 协议分析和 OpenDaylight 安装
    实验 4:Open vSwitch 实验——Mininet 中使用 OVS 命令
    软件工程第一次作业
    实验 3:Mininet实验——测量路径的损耗率
    软件工程个人总结
    2020 SDN第七次上机实验
    软件工程实践第4次作业-结对编程之实验室程序实现
    2020 SDN第六次上机实验
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148419.html
Copyright © 2020-2023  润新知