UVA10369- Arctic Network

题目大意:

南极有n个科研站, 要把这些站用卫星或者无线电连接起来,使得任意两个都能直接或者间接相连。任意两个都有安装卫星设备的,都可以直接通过卫星通信,不管它们距离有多远。 而安装有无线电设备的两个站,距离不能超过D。 D越长费用越多。

现在有s个卫星设备可以安装,还有足够多的无线电设备,求一个方案,使得费用D最少(D取决与所有用无线电通信的花费最大的那条路径)。


分析与总结:

很自然的想到求最小生成树,然后为了使得D费用最少,就要让其中路径最长的那些用来安装卫星。 s个通信卫星可以安装s-1条最长的那些路径。 那么, 最小生成树中第p-s大的路径长度就是D。

只需要求出最小生成树上的所有路径长度,排好序,边得到答案。(借鉴)


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define N 250005

using namespace std;

struct state{
    int l, r;
    double value;
}s[N];

int n, m, cnt, f[N], x[N], y[N];
double ans;

bool cmp(const state& a, const state& b) {
    return b.value - a.value > 1e-9;
}

int getFather(int x) {
    x == f[x] ? x : f[x] = getFather(f[x]); 
}

void init() {
    cnt = 0;
    memset(x, 0, sizeof(x));
    memset(y, 0, sizeof(y));
    scanf("%d %d", &n, &m); 
    for (int i = 0; i < m; i++) {
        f[i] = i;
        scanf("%d %d", &x[i], &y[i]); 
        for (int j = 0; j < i; j++) {
            s[cnt].value = sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j])); 
            s[cnt].l = i; 
            s[cnt].r = j; 
            cnt++;
        }     
    }
    sort(s, s + cnt, cmp);
}

void kruskal() {
    int t = m - n - 1;
    for (int i = 0; i < cnt; i++) { 
        int p = getFather(s[i].l);
        int q = getFather(s[i].r); 
        if (p != q) {
            ans = s[i].value;
            if (t) {
                t--; 
                f[q] = p; 
            }
            else
                return;
        } 
    }
}

int main() {
    int cas;
    scanf("%d", &cas);
    while (cas--) {
        init();  
        kruskal(); 
        printf("%.2lf\n", ans);
    }
    return 0;
}


你可能感兴趣的:(UVA10369- Arctic Network)