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+12\sim 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≤1001\le n\le 500, 0\le x, y\le 10^4, 0\le k\le 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\n",sqrt(d[n-k+1]));
    return 0;
}
View Code

謝謝大家!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM