AcWing 1145. 北極通訊網絡 (kruskal最小生成樹+連通塊)

整理的算法模板:ACM算法模板總結(分類詳細版)

 

北極的某區域共有 nn 座村莊,每座村莊的座標用一對整數 (x,y)(x,y) 表示。

爲了加強聯繫,決定在村莊之間建立通訊網絡,使每兩座村莊之間都可以直接或間接通訊。

通訊工具可以是無線電收發機,也可以是衛星設備。

無線電收發機有多種不同型號,不同型號的無線電收發機有一個不同的參數 dd,兩座村莊之間的距離如果不超過 dd,就可以用該型號的無線電收發機直接通訊,dd 值越大的型號價格越貴。現在要先選擇某一種型號的無線電收發機,然後t統一給所有村莊配備,數量不限,但型號都是 相同的

配備衛星設備的兩座村莊無論相距多遠都可以直接通訊,但衛星設備是 有限的,只能給一部分村莊配備。

現在有 kk 臺衛星設備,請你編一個程序,計算出應該如何分配這 kk 臺衛星設備,才能使所配備的無線電收發機的 dd 值最小。

例如,對於下面三座村莊:

1.png

其中,|AB|=10,|BC|=20,|AC|=105√≈22.36|AB|=10,|BC|=20,|AC|=105≈22.36。

如果沒有任何衛星設備或只有 11 臺衛星設備 (k=0k=0 或 k=1k=1),則滿足條件的最小的 d=20d=20,因爲 AA 和 BB,BB 和 CC 可以用無線電直接通訊;而 AA 和 CC 可以用 BB 中轉實現間接通訊 (即消息從 AA 傳到 BB,再從 BB 傳到 CC);

如果有 22 臺衛星設備 (k=2k=2),則可以把這兩臺設備分別分配給 BB 和 CC ,這樣最小的 dd 可取 1010,因爲 AA 和 BB 之間可以用無線電直接通訊;BB 和 CC 之間可以用衛星直接通訊;AA 和 CC 可以用 BB 中轉實現間接通訊。

如果有 33 臺衛星設備,則 A,B,CA,B,C 兩兩之間都可以直接用衛星通訊,最小的 dd 可取 00。

輸入格式

第一行爲由空格隔開的兩個整數 n,kn,k;

接下來 nn 行,每行兩個整數,第 ii 行的 xi,yixi,yi 表示第 ii 座村莊的座標 (xi,yixi,yi)。

輸出格式

一個實數,表示最小的 dd 值,結果保留 22 位小數。

數據範圍

1≤n≤5001≤n≤500,
0≤x,y≤1040≤x,y≤104,
0≤k≤1000≤k≤100

輸入樣例:

3 2
10 10
10 0
30 0

輸出樣例:

10.00

 

 思路:

首先既然有k個衛星可以用,那麼我們儘可能的將衛星用於連接k個連通塊;剛開始有n個連通塊,用kruskal算法從小到大處理所有邊,每次記錄當前連通塊剩餘個數res,當res==k時,就可以用衛星將所有的連通塊連接起來;類似於貪心的思想,這樣的到的一定是最小的;

#include <bits/stdc++.h>
using namespace std;
const int N=505,M=505*505;
int x[N],y[N],cnt,p[N],n,k;
struct node
{
    int a,b;
    double dis;
}e[M];
bool cmp(node a,node b)
{
    return a.dis<b.dis;
}
double get(int a,int b,int c,int d)
{
    return sqrt((a-c)*(a-c)+(b-d)*(b-d));
}
int find(int x)
{
    if(p[x]!=x)
    {
        p[x]=find(p[x]);
    }
    return p[x];
}
double kruskal()
{
    double res=0;
    for(int i=0;i<=n;i++) p[i]=i;
    for(int i=0;i<cnt;i++)
    {
        if(n<=k) return res;
        int a=find(e[i].a),b=find(e[i].b);
        if(a!=b)
        {
            p[a]=b;
            n--;
            res=e[i].dis;
        }
    }
    return res;
}
int main()
{
    cin >>n>>k;
    for(int i=0;i<n;i++) cin >>x[i]>>y[i];
    for(int i=0;i<n;i++)
    {
        for(int j=i+1;j<n;j++)
        {
            double dis=get(x[i],y[i],x[j],y[j]);
            e[cnt++]={i,j,dis};
        }
    }
    sort(e,e+cnt,cmp);
    printf("%.2f",kruskal());
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章