Files
python/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1145.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

74 lines
2.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}