题意:
n个站点,s个卫星信号无视距离,剩下电波信号限制距离D,求D最小
分析:
按照求最小生成树的顺序选边,倒数n-s+1就是D的值
注意,一般有打印double的题目要用C++提交不能用G++提交,否则WA.
代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 2010;
const int M = 2000 * 2000 + 10;
int s;
struct Edge {
int u, v;
double dis;
Edge () {}
Edge ( int u, int v, double d )
: u ( u )
, v ( v )
, dis ( d ) {}
bool operator< ( const Edge &rhs ) const { return dis < rhs.dis; }
};
struct Kruskal {
int n, m;
Edge edges[ M ];
int fa[ N ];
int findset ( int x ) { return fa[ x ] == -1 ? x : fa[ x ] = findset ( fa[ x ] ); }
void init ( int _n ) {
n = _n;
m = 0;
memset ( fa, -1, sizeof ( fa ) );
}
void AddEdge ( int u, int v, double d ) { edges[ m++ ] = Edge ( u, v, d ); }
double kruskal () {
int sum = 0, cnt = 0;
sort ( edges, edges + m );
for ( int i = 0; i < m; ++i ) {
int u = edges[ i ].u, v = edges[ i ].v;
if ( findset ( u ) != findset ( v ) ) {
fa[ findset ( u ) ] = findset ( v );
sum += edges[ i ].dis;
if ( ++cnt >= n - s )
return edges[ i ].dis;
}
}
return -1;
}
} KK;
int x[ N ], y[ N ];
double get_dis ( int i, int j ) {
return sqrt ( double( ( x[ i ] - x[ j ] ) * ( x[ i ] - x[ j ] ) +
( y[ i ] - y[ j ] ) * ( y[ i ] - y[ j ] ) ) );
}
int main () {
int kse;
scanf ( "%d", &kse );
while ( kse-- ) {
int n;
scanf ( "%d%d", &s, &n );
KK.init ( n );
for ( int i = 0; i < n; ++i )
scanf ( "%d%d", &x[ i ], &y[ i ] );
for ( int i = 0; i < n; ++i )
for ( int j = 0; j < n; ++j )
KK.AddEdge ( i, j, get_dis ( i, j ) );
double sol = KK.kruskal ();
printf ( "%.2lf\n", sol );
}
return 0;
}