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.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> 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;
}