这道题开始以为是求最小生成树,然后写出来之后发现和样例输出不符合,再看了一遍题,发现
求所有的点之间的最大通信成本D。其中有s个卫星频道,可以和任一点连线。我们要降低成本的话就是让
远的点用卫星频道,用kruskal算法合并到有 P - S棵树组成的森林,其中后S个点分别单独为一棵树,
使用卫星频道。前面的点用的则为radio通信,然后合并到符合条件时取得的边为radio的最大边。
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>
#define MAXD 510
int p[MAXD], r[MAXD * MAXD], u[MAXD * MAXD], v[MAXD * MAXD];
double x[MAXD], y[MAXD], w[MAXD * MAXD], ans;
int N, S, P, t, nx, ny;
double distance( int i, int j)
{
return sqrt( (x[i] - x[j]) * ( x[i] - x[j]) + ( y[i] - y[j]) * ( y[i] - y[j]));
}
int find_set( int x)
{
return p[x] == x ? x : ( p[x] = find_set( p[x]));
}
int cmp( const void *_p, const void *_q)
{
int *p = (int *)_p;
int *q = (int *)_q;
return w[*p] > w[*q] ? 1 : - 1;
}
void init()
{
scanf( "%d%d", &S, &P);
for( int i = 0; i < P; i ++)
scanf( "%lf%lf", &x[i], &y[i]);
t = 0;
for( int i = 0; i < P; i ++)
for( int j = i + 1; j < P; j ++)
{
u[t] = i;
v[t] = j;
w[t ++] = distance( i ,j);
}
}
void kruskal()
{
ans = 0.0;
for( int i = 0; i < P; i ++)
p[i] = i;
for( int i = 0; i < t; i ++)
r[i] = i;
qsort( r, t, sizeof (r[0]), cmp);
int cnt = 0;
for( int i = 0; i < t; i ++)
{
int e = r[i];
nx = find_set( u[e]);
ny = find_set( v[e]);
if( nx != ny) {
ans = w[e];
p[nx] = ny;
cnt ++;
}
if( cnt == P - S) break;
}
}
int main()
{
scanf( "%d", &N);
while( N --)
{
init();
kruskal();
printf( "%.2f\n", ans);
}
return 0;
}