题意:
实际上就是求最小生成树的n-k条边的最短是多少(剩余k条可直达不计长度)
思路:
又是求最小生成树,这次用kruskal算法
1.求出所有的距离
2.将距离排序,只要是没纳入的点就纳入一直到
所有的点都纳入(用并查集判断是否纳入)
代码:
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
int sets[501];
double x[501], y[501];
int m, n;
int num;
int f[501*501];
int rank[501*501];
double ans[501*501];
struct edge {
int u, v;
double w;
bool operator < (const edge a) const{
return w<a.w;
}
}e[501*501];
inline void init() {
for(int i=0; i<n*n; i++) {
f[i] = i;
rank[i] = 0;
}
}
double dist(double x1, double y1, double x2, double y2) {
return sqrt((x1-x2)*(x1-x2) +(y1-y2)*(y1-y2));
}
int find(int x) {
return f[x]==x?x:find(f[x]);
}
bool uni(int x, int y) {
x = find(x);
y = find(y);
if(x == y) return false;
if(rank[x] > rank[y]) f[y] = x;
else {
f[x] = y;
if(rank[y] == rank[x])
rank[y]++;
}
return true;
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&m,&n);
init();
for(int i=1; i<=n; ++i)
scanf("%lf%lf",&x[i],&y[i]);
int pos=0;
for(int i=1; i<=n; ++i){
for(int j=i+1; j<=n; ++j)if(i!=j){
e[pos].u=i, e[pos].v=j;
e[pos++].w = dist(x[i],y[i],x[j],y[j]);
}
}
sort(e,e+pos);
int k=0;
for(int i=0; i<pos; ++i){
if(uni(e[i].u,e[i].v)){
ans[k++] = e[i].w;
}
}
printf("%.2f\n", ans[k-m]);
}
return 0;
}