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

題幹:

北極的某區域共有 n 座村莊,每座村莊的座標用一對整數 (x,y 表示。
爲了加強聯繫,決定在村莊之間建立通訊網絡,使每兩座村莊之間都可以直接或間接通訊。
通訊工具可以是無線電收發機,也可以是衛星設備。
無線電收發機有多種不同型號,不同型號的無線電收發機有一個不同的參數 d,兩座村莊之間的距離如果不超過 d,就可以用該型號的無線電收發機直接通訊,d 值越大的型號價格越貴。現在要先選擇某一種型號的無線電收發機,然後t統一給所有村莊配備,數量不限,但型號都是 相同的。
配備衛星設備的兩座村莊無論相距多遠都可以直接通訊,但衛星設備是 有限的,只能給一部分村莊配備。
現在有 k 臺衛星設備,請你編一個程序,計算出應該如何分配這 k 臺衛星設備,才能使所配備的無線電收發機的 d 值最小。
例如,對於下面三座村莊:

在這裏插入圖片描述
其中,|AB=10,BC=20,AC=10522.36AB|=10,|BC|=20,|AC|=10\sqrt5≈22.36
如果沒有任何衛星設備或只有 1 臺衛星設備 (k=0 或 k=1),則滿足條件的最小的 d=20,因爲 A 和 B,B 和 C 可以用無線電直接通訊;而 A 和 C 可以用 B 中轉實現間接通訊 (即消息從 A 傳到 B,再從 B 傳到 C);
如果有 2 臺衛星設備 (k=2),則可以把這兩臺設備分別分配給 B 和 C ,這樣最小的 d 可取 10,因爲 A 和 B 之間可以用無線電直接通訊;B 和 C 之間可以用衛星直接通訊;A 和 C 可以用 B 中轉實現間接通訊。
如果有 3 臺衛星設備,則 A,B,C 兩兩之間都可以直接用衛星通訊,最小的 d 可取 0。
輸入格式
第一行爲由空格隔開的兩個整數 n,k;
接下來 n 行,每行兩個整數,第 i 行的 xi,yi 表示第 i 座村莊的座標 (xi,yi)。
輸出格式
一個實數,表示最小的 d 值,結果保留 2 位小數。

數據範圍
1n500,1≤n≤500,
0x,y104,0≤x,y≤10^4,
0k1000≤k≤100
輸入樣例:
3 2
10 10
10 0
30 0
輸出樣例:
10.00

思路:

總結下題意,兩個村莊間可以通過無線電設備連接(有費用)或通過衛星設備連接(無費用);所有村莊配備的無線電設備距離(即費用)是一樣的,求使所有存在都相鄰的最小無線電設備距離。
既然衛星設備相連沒有花費,那肯定選距離遠的邊。
按照kruskal算法求最小生成樹,然後當剩下的點<=k時就可以結束了。
這樣就只需要求村莊間距離,因爲給出的是座標,所以先按座標公式得出距離,然後求最小生成樹。
注意要求的保留兩位小數的最大無線電通信距離的最小值。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
struct stu{
    int x,y;
    double w;
    bool operator <(const stu &t)const{
        return w<t.w;
    }  
}edge[250010];
int x[510],y[510],tot,f[510];
int find(int i){
    if(f[i]==i) 
        return i;
    return f[i]=find(f[i]);
}
int main(){
    int n,k;
    double dis;
    scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++){
        scanf("%d%d",&x[i],&y[i]);
        for(int j=0;j<i;j++){
            dis=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
            edge[tot++]={i,j,dis};
        }
        f[i]=i;
    }
    sort(edge,edge+tot);
    int cnt=n;
    double ans=0;
    for(int i=0;i<tot;i++){
        if(cnt<=k)  break;
        int fx=find(edge[i].x),fy=find(edge[i].y);
        //printf("%d %d\n",fx,fy);
        if(fx!=fy){
            f[fx]=fy;
            ans=edge[i].w;
            cnt--;
            //printf("%lf\n",edge[i].w);
        }
    }
    printf("%.2lf\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章