题目大意:
南极有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;
}