#include using namespace std; typedef pair PII; #define x first #define y second const int N = 510, M = N * N / 2; // C(n,2) int n, k; struct Edge { int a, b; double c; const bool operator<(const Edge &t) const { return c < t.c; } } edge[M]; int el; // 每个村庄的坐标 PII q[M]; // 欧几里得距离 double get_dist(PII a, PII b) { int x = a.x - b.x, y = a.y - b.y; return sqrt(x * x + y * y); } // 并查集 int p[N]; int find(int x) { if (p[x] != x) p[x] = find(p[x]); return p[x]; } int main() { cin >> n >> k; // n座村庄,有k台卫星设备 for (int i = 0; i < n; i++) cin >> q[i].x >> q[i].y; // 村庄坐标 // 枚举所有点与点之间的边 for (int i = 0; i < n; i++) for (int j = i + 1; j < n; j++) edge[el++] = {i, j, get_dist(q[i], q[j])}; // 因为是一个无向图,所以我们取一半就可以了 // 之所以取一半,其实也是为了配合后面的 cnt--,因为cnt--的现实含义是两个点连接上了,家族数量减少了1个 // 如果这里不是取一半,那么后面就需要cnt-=2, 哈哈,就问你是不是懵~ // 边权由小到大排序 sort(edge, edge + el); // 并查集初始化 for (int i = 0; i < n; i++) p[i] = i; int cnt = n; // 剩余的连通块数量 double res = 0; // 原则:长的用卫星,短的用无线电收发机 // 合并完之后,正好剩下k个连通块,停止,每个连通块上安装卫星即可全面通讯 // 给原图的节点中n - k个节点生成一棵最小生成树 for (int i = 0; i < el; i++) { // 枚举每条边 if (cnt == k) break; // 剩余点数为k时停止, 在这k个点上建立卫星站 int a = edge[i].a, b = edge[i].b; double c = edge[i].c; a = find(a), b = find(b); if (a != b) { p[a] = b; res = c; // 不停的记录参数d的上限 cnt--; // 连通块数量-1 } } printf("%.2lf\n", res); return 0; }