社区讨论
40pts 注释我自认为写的很详细
P1991无线通讯网参与者 2已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @m4jnc9mg
- 此快照首次捕获于
- 2024/12/11 16:46 去年
- 此快照最后确认于
- 2025/11/04 13:01 4 个月前
卫星电话 -> 微信电话。
因为只要有网,微信电话就能打(doge)。
CPP#include <iostream> // macOS 用不了那个东西
#include <vector>
#include <algorithm>
#include <cmath>
#define MAXN 505
using namespace std;
struct Point {
int x, y;
Point() {
x = y = 0;
}
} a[MAXN]; // 每个点
struct Edge{
int u, v;
double l;
} e[MAXN*MAXN]; // 每条边
int k, n, m, fa[MAXN]; // k 表示可以安装微信电话的数量,n 表示哨所的数量,m 表示边的数量
bool vis[MAXN]; // 这个节点是否安装了微信电话
double distBetween(Point a, Point b) {
return sqrt(pow(a.x-b.x, 2.0)+pow(a.y-b.y, 2.0));
}
int find(int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void merge(int x, int y) {
fa[find(x)] = find(y);
}
bool operator< (Edge a, Edge b) { // 排序边用到
return a.l < b.l;
}
bool operator> (Edge a, Edge b) { // 排序边用到
return a.l > b.l;
}
int main() {
cin >> k >> n;
for (int i = 1; i <= n; i++) { // 输入并初始化并查集
cin >> a[i].x >> a[i].y;
fa[i] = i;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (i == j) continue;
e[++m].u = i;
e[m].v = j;
e[m].l = distBetween(a[i], a[j]);
}
}
sort(e+1, e+m+1);
vector<Edge> selectedEdge; // 选择的边(名字写的很明白了吧。。。)
for (int i = 1; i <= m; i++) { // Kruskal 启动!
if (find(e[i].u) != find(e[i].v)) {
selectedEdge.push_back(e[i]);
merge(e[i].u, e[i].v);
}
}
sort(selectedEdge.begin(), selectedEdge.end(), greater<Edge>()); // 从大到小排序
int ansindex = 0;
for (int i = 0; i < selectedEdge.size(); i++) {
int u = selectedEdge[i].u, v = selectedEdge[i].v;
if (k <= 0) break; // 如果微信电话用完了
if (!vis[u]) { // 如果 u 没装微信电话
vis[u] = 1;
k--;
}
if (!vis[v]) { // 如果 v 没装微信电话
vis[v] = 1;
k--;
}
ansindex = i;
}
printf("%.2f\n", selectedEdge[++ansindex].l);
// 因为 ansindex 是最后一对安装微信电话的边,那么第一对没有安装的就是答案
return 0;
}
回复
共 2 条回复,欢迎继续交流。
正在加载回复...