zoukankan      html  css  js  c++  java
  • LOJ#10065. 「一本通 3.1 例 2」北极通讯网络

    题目链接:https://loj.ac/problem/10065

    题目描述

    原题来自:Waterloo University 2002

    北极的某区域共有 nnn 座村庄,每座村庄的坐标用一对整数 (x,yx, yx,y) 表示。为了加强联系,决定在村庄之间建立通讯网络。通讯工具可以是无线电收发机,也可以是卫星设备。所有的村庄都可以拥有一部无线电收发机, 且所有的无线电收发机型号相同。但卫星设备数量有限,只能给一部分村庄配备卫星设备。

    不同型号的无线电收发机有一个不同的参数 ddd,两座村庄之间的距离如果不超过 ddd 就可以用该型号的无线电收发机直接通讯,ddd 值越大的型号价格越贵。拥有卫星设备的两座村庄无论相距多远都可以直接通讯。

    现在有 kkk 台卫星设备,请你编一个程序,计算出应该如何分配这 kkk 台卫星设备,才能使所拥有的无线电收发机的 ddd 值最小,并保证每两座村庄之间都可以直接或间接地通讯。

    例如,对于下面三座村庄:

    Picture1

    其中 |AB|=10,|BC|=20,|AC|=10522.36

    如果没有任何卫星设备或只有 111 台卫星设备 (k=0k=0k=0 或 k=1k=1k=1),则满足条件的最小的 d=20d = 20d=20,因为 AAA 和 BBB,BBB 和 CCC 可以用无线电直接通讯;而 AAA 和 CCC 可以用 BBB 中转实现间接通讯 (即消息从 AAA 传到 BBB,再从 BBB 传到 CCC);

    如果有 222 台卫星设备 (k=2k=2k=2),则可以把这两台设备分别分配给 BBB 和 CCC ,这样最小的 ddd 可取 101010,因为 AAA 和 BBB 之间可以用无线电直接通讯;BBB 和 CCC 之间可以用卫星直接通讯;AAA 和 CCC 可以用 BBB 中转实现间接通讯。

    如果有 333 台卫星设备,则 A,B,CA,B,CA,B,C 两两之间都可以直接用卫星通讯,最小的 ddd 可取 000。

    输入格式

    第一行为由空格隔开的两个整数 n,kn,kn,k;

    2∼n+12sim n+12n+1 行,每行两个整数,第 iii 行的 xi,yix_i,y_ixi​​,yi​​ 表示第 iii 座村庄的坐标 (xi,yix_i, y_ixi​​,yi​​)。

    输出格式

    一个实数,表示最小的 ddd 值,结果保留 222 位小数。

    样例

    样例输入

    3 2
    10 10
    10 0
    30 0

    样例输出

    10.00

    数据范围与提示

    对于全部数据,1≤n≤500,0≤x,y≤104,0≤k≤1001le nle 500, 0le x, yle 10^4, 0le kle 1001n500,0x,y104​​,0k100。

    题解

           自己做这道题的时候,YY了一个跟正解一样的思路,但却不知道怎么证。

           后来到网上找了找,发现了一篇很好的证明。

           当然,只要证出来了,代码就很简单了。

           证明如下:

           当正向思考受阻时,逆向思维可能有奇效。本题就是这样。知道卫星设备的数量,求最小的收发距离,可能比较困难;如果知道距离求数量,就很简单了。把所有可以互相通讯的村庄连接起来,构成一个图。卫星设备的台数就是图的连通支的个数。

           问题转化为:找到一个最小的d,使得把所有权值大于d的边去掉之后,连通支的个数小于等于k。

           先看一个定理。定理2:如果去掉所有权值大于d的边后,最小生成树被分割成为k个连通支,图也被分割成为k个连通支。

           证明:用反证法。假设原图被分割成k’ (k'≠k)个连通支,显然不可能k’>k,所以k’<k。因此在某一图的连通支中,最小生成树被分成了至少两部分,不妨设其为T1,T2。因为T1和T2同属于一个连通支,所以一定存在x∈T1,y∈T2,w(x,y)≤d。又因为在整个最小生成树中,所以x到y的路径中一定存在一条权值大于d的边(u,v)(否则x和y就不会分属于T1和T2了),w(x,y)≤d<w(u,v),所以把(x,y)加入,把(u,v)去掉,将得到一棵总权值比最小生成树还小的生成树。这显然是不可能的。所以,原命题成立。(证毕)

           有了这个定理,很容易得到一个构造算法:最小生成树的第k长边就是问题的解。

           首先,d取最小生成树中第k长的边是可行的。如果d取第k长的边,我们将去掉最小生成树中前k-1长的边,最小生成树将被分割成为k部分。由定理2,原图也将分割成为k部分。(可行性)

           其次,如果d比最小生成树中第k长的边小的话,最小生成树至少被分割成为k+1部分,原图也至少被分割成为k+1部分。与题意不符。(最优性)

           综上所述,最小生成树中第k长的边是使得连通支个数≤k的最小的d,即问题的解。

    代码

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int n,k,x[510],y[510],d[510];
    bool vis[510];
    int cc(int i,int j){return(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);}
    int main() 
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&x[i],&y[i]);
            d[i]=cc(1,i);
        }
        for(int i=1;i<n;i++)
        {
            int mi=2e9,k;
            for(int j=2;j<=n;++j)if(!vis[j]&&d[j]<mi)mi=d[k=j];
            vis[k]=1;
            for(int j=2;j<=n;++j)if(!vis[j])d[j]=std::min(d[j],cc(k,j));
        }
        std::sort(d+1,d+1+n);
        printf("%.2lf
    ",sqrt(d[n-k+1]));
        return 0;
    }
    View Code

    谢谢大家!

  • 相关阅读:
    SQLServer 时间差运算
    phpStudy
    解决Apache/PHP无法启动的问题
    apche的主配置文件)
    知识总结
    学完了js的知识,一起分享总结知识点
    JS的学习体会与分享
    SpringBoot -- pom.xml文件
    c++基本知识点
    c语言基本常识5
  • 原文地址:https://www.cnblogs.com/mxrmxr/p/9846958.html
Copyright © 2011-2022 走看看