【P1911】無線通訊網 kruskal

無神論者大祭司發表於2020-12-28

P1911


連結

分析

這是一個最小生成樹的問題,其實只要模擬一下即可。兩種通訊方式,無線電和衛星通訊,假設共m個點,衛星電話是n個。當n < 2的時候實際上就是一個最小生成樹問題,而當n = 2的時候我們可以去掉最小生成樹上的最長邊,通過衛星電話向連結,n > 2時操作也一樣,衛星電話只是改變了kruskal演算法終止的條件,由原先的count = m - 1變為count = m - n 由此我們可以得到一下的程式碼

程式碼

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;
const int N = 505, M = 2e5 + 10;
int n, m, cnt;
int X[N], Y[N], par[N];

struct edge{
    int fr, to;
    double dis;
}e[M];

void add(int u, int v, double w){
    e[++cnt] = {u, v, w};
}

bool cmp(const edge& a, const edge& b){
    return a.dis < b.dis;
}
double dist(int p1, int p2){
    return sqrt((X[p1] - X[p2])*(X[p1] - X[p2]) + (Y[p1] - Y[p2])*(Y[p1] - Y[p2]));
}

int find(int x){
    return x == par[x] ? x: (par[x] = find(par[x]));
}

int main() {
    cin >> n >> m;
    for (int i = 1; i <= m; ++i){
        par[i] = i;
        cin >> X[i] >> Y[i];
    }

    for (int i = 1; i <= m; ++i)
        for (int j = i + 1; j <= m; ++j)
            add(i, j, dist(i, j));
    sort(e + 1, e + 1 + cnt, cmp);

    int count = 0;
    double res = 0;
    for (int i = 1; i <= cnt; ++i) {
        int x = find(e[i].fr), y = find(e[i].to);
        if (x != y){
            par[x] = y;
            res = e[i].dis;
            if (++count == m - n) break;
        }
    }
    printf("%.2f", res);
    return 0;
}

相關文章