You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

74 lines
2.0 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
#define x first
#define y second
const int N = 510;
// 有向图 边数最多n(n-1)/2
// 可以想象一下每个点可以向其它n-1个点引边共有n个点就是n*(n-1)条边,因为一来一回算了两次,所以就是 n*(n-1)/2个最大值设定 N*N/2
const int M = N * N / 2;
int n, k;
struct Edge {
int a, b;
double w;
const bool operator<(const Edge &t) const {
return w < t.w;
}
} e[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++)
// 记录单向边即可
e[el++] = {i, j, get_dist(q[i], q[j])};
// 边权由小到大排序
sort(e, e + 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 = find(e[i].a), b = find(e[i].b);
if (a != b) {
p[a] = b;
cnt--; // 连通块数量-1
res = e[i].w; // 不停的记录参数d的上限
}
}
printf("%.2lf\n", res);
return 0;
}