题目描述
北极的某区域共有 n 座村庄,每座村庄的坐标用一对整数 (x,y) 表示。为了加强联系,决定在村庄之间建立通讯网络。通讯工具可以是无线电收发机,也可以是卫星设备。所有的村庄都可以拥有一部无线电收发机, 且所有的无线电收发机型号相同。但卫星设备数量有限,只能给一部分村庄配备卫星设备。
不同型号的无线电收发机有一个不同的参数 d,两座村庄之间的距离如果不超过 d 就可以用该型号的无线电收发机直接通讯,d 值越大的型号价格越贵。拥有卫星设备的两座村庄无论相距多远都可以直接通讯。
现在有 k 台卫星设备,请你编一个程序,计算出应该如何分配这 k 台卫星设备,才能使所拥有的无线电收发机的 d 值最小,并保证每两座村庄之间都可以直接或间接地通讯。
输入
第一行为由空格隔开的两个整数 n,k;
第 2∼n+1 行,每行两个整数,第 i 行的 xi,yi 表示第 i 座村庄的坐标 (xi,yi)。
输出
一个实数,表示最小的 d 值,结果保留 2 位小数。
输入样例
3 2
10 10
10 0
30 0
输出样例
10.00
思路
题目的意思是求最小生成树的第k大的边的长度
#include<bits/stdc++.h>
#define read() freopen("input.txt","r",stdin)
#define write() freopen("output.txt","w",stdout)
using namespace std;
const int maxn = 1e6+10;
int pre[505];
vector<double>v;
struct dot{
int start,end;
double len;
}city[maxn];
struct poi{
int x,y;
}s1[505];
double getdis(poi a,poi b){
return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));
}
int find(int x){
return x==pre[x]?x:pre[x]=find(pre[x]);
}
bool cmp(dot a,dot b){
return a.len<b.len;
}
int main(){
read();write();
int k,n,cnt=0;
cin>>n>>k;
for( int i=1; i<=n; i++ ) pre[i]=i;
for( int i=0; i<n; i++ ) cin>>s1[i].x>>s1[i].y;
for( int i=0; i<n; i++ ){
for( int j=i+1; j<n; j++ ){
city[cnt].start=i;city[cnt].end=j;
city[cnt++].len=getdis(s1[i],s1[j]);
}
}
sort(city,city+cnt,cmp);
for( int i=0; i<cnt; i++ ){
int a=find(city[i].start);
int b=find(city[i].end);
if(a!=b){
pre[a]=b;
v.push_back(city[i].len);
}
}
sort(v.begin(),v.end(),greater<double>());
printf("%.2f",v[k-1]);
return 0;
}