思路:按边权排序跑kruskal最小生成树,使用并查集合并时每次扩展一个结点,当未扩展的结点数为k-1的时候,说明剩下的结点可以互相通讯并且能与当前生成树通讯,此时退出循环即可
合并完再删是错误的,如图如果有4台卫星设备,如果是删掉最大的两条边应该是1,2,3,4配置设备,但实际上是2,3,4,5配置设备
#include<iostream>
#include<string>
#include<vector>
#include<cmath>
#include<algorithm>
#include<set>
#include<stack>
#include<map>
#include<cstring>
#include<queue>
using namespace std;
const int N = 505;
int pos[N][2], p[N];
bool vis[N];
typedef long long ll;
int find(int x) {
return x == p[x] ? x : (p[x] = find(p[x]));
}
ll getDist(int r1, int c1, int r2, int c2) {
return (r1 - r2) * (r1 - r2) + (c1 - c2) * (c1 - c2);
}
bool cmp(vector<ll>& a, vector<ll>& b) {
return a[2] < b[2];
}
int main()
{
int n, k;
cin >> n >> k;
for (int i = 0; i < n; i++) cin >> pos[i][0] >> pos[i][1], p[i] = i;
if(k >= n) {
cout << "0.00";
return 0;
}
vector<vector<ll>> e;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
e.push_back({ i, j, getDist(pos[i][0], pos[i][1], pos[j][0], pos[j][1]) });
}
}
sort(e.begin(), e.end(), cmp);
int cnt = 1;
double ans = 0;
for (int i = 0; i < e.size(); i++) {
auto v = e[i];
if (find(v[0]) != find(v[1])) {
p[find(v[0])] = find(v[1]);
ans = v[2];
++cnt;
if(n - cnt == k - 1) {
break;
}
}
}
ans = sqrt(ans);
printf("%.2f", ans);
return 0;
}