题目大意:
南极有n个科研站, 要把这些站用卫星或者无线电连接起来,使得任意两个都能直接或者间接相连。任意两个都有安装卫星设备的,都可以直接通过卫星通信,不管它们距离有多远。 而安装有无线电设备的两个站,距离不能超过D。 D越长费用越多。
现在有s个卫星设备可以安装,还有足够多的无线电设备,求一个方案,使得费用D最少(D取决与所有用无线电通信的花费最大的那条路径)。
分析与总结:
很自然的想到求最小生成树,然后为了使得D费用最少,就要让其中路径最长的那些用来安装卫星。 s个通信卫星可以安装s-1条最长的那些路径。 那么, 最小生成树中第p-s大的路径长度就是D。
只需要求出最小生成树上的所有路径长度,排好序,边得到答案。
CODE:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
using
namespace std;
#define MAXN 1100
#define INF 0X3F3F3F3F
int n, k, m;
struct node
{
double x, y;
}a[MAXN*MAXN];
struct Edge
{
int u, v;
double w;
}edge[MAXN*MAXN];
int p[MAXN], tot;
int cmp(
const Edge a,
const Edge b)
{
return a.w < b.w;
}
double w[MAXN][MAXN], d[MAXN];
void init()
{
tot =
0;
}
double dist(
const node a,
const node b)
{
return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
int find(
int x)
{
return x == p[x]? x : p[x] = find(p[x]);
}
void Kruskal()
{
double ans =
0;
int count =
0;
for(
int i =
0; i <= n; i++) p[i] = i;
sort(edge, edge+tot, cmp);
for(
int i =
0; i < tot; i++)
{
int x = find(edge[i].u), y = find(edge[i].v);
if(x != y)
{
ans = edge[i].w;
p[x] = y;
count++;
}
if(count == n-m)
{
printf(
"
%.2lf\n
", ans);
return ;
}
}
}
int main()
{
int T;
scanf(
"
%d
", &T);
while(T--)
{
init();
scanf(
"
%d%d
", &m, &n);
for(
int i =
1; i <= n; i++) scanf(
"
%lf%lf
", &a[i].x, &a[i].y);
for(
int i =
1; i <= n; i++)
{
for(
int j =
1; j <= n; j++)
if(i != j)
{
edge[tot].u = i, edge[tot].v = j;
edge[tot].w = dist(a[i], a[j]);
tot++;
}
}
Kruskal();
}
return
0;
}