社区讨论
请问为什么一定是s-1条边用卫星电话通讯
P1991无线通讯网参与者 4已保存回复 4
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 4 条
- 当前快照
- 1 份
- 快照标识符
- @luza20q5
- 此快照首次捕获于
- 2024/04/14 16:42 2 年前
- 此快照最后确认于
- 2024/04/14 19:49 2 年前
一开始我用一个很复杂的思路写了个kruscal
然后只得了60分
(可能有点复杂……)
CPP#include <cmath>
#include <queue>
#include <vector>
#include <bitset>
#include <climits>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define debug(x) (cerr << x << '\n')
using namespace std;
const int N = 505;
int s, p;
double ans = 0.0;
vector<int> fa(N);
bitset<N> hasPhone; /* 判断哨所是否有卫星电话 */
struct Node {
double x;
double y;
};
vector<Node> a;
struct Edge {
int from;
int to;
double w;
bool operator < (const Edge& a) const {
return w < a.w;
}
};
vector<Edge> edge;
inline void init() {
for (int i = 0; i < N; i++) {
fa[i] = i;
}
}
inline double dis(const int& i1, const int& i2) {
/* 哨所距离 */
return sqrt(pow(abs(a[i1].x - a[i2].x), 2) + \
pow(abs(a[i1].y - a[i2].y), 2));
}
inline int find(const int& u) {
return fa[u] == u ? u : fa[u] = find(fa[u]);
}
void kruscal() {
priority_queue<Edge> pq; /* 存用过的最大的边 */
sort(edge.begin(), edge.end());
/* for循环结束后ans为最长边 */
for (auto x : edge) {
if (find(x.from) == find(x.to)) {
continue;
}
fa[find(x.from)] = find(x.to);
ans = x.w;
pq.push(x);
}
// for (int i = 1; i <= s - 1; i++) {
while (s > 0) {
/* 目前边权最大的边 */
Edge x = pq.top();
pq.pop();
/* 如果起点没有卫星电话 */
if (!hasPhone[x.from]) {
/* 判断剩的卫星电话够不够用 */
if (s < 1) {
break;
} else {
/* 给起点安装卫星电话 */
s--;
hasPhone[x.from] = true;
}
}
/* 如果终点没有卫星电话 */
if (!hasPhone[x.to]) {
/* 判断剩的卫星电话够不够用 */
if (s < 1) {
break;
} else {
/* 给终点安装卫星电话 */
s--;
hasPhone[x.to] = true;
}
}
/* 如果ans是当前处理的值 */
if (ans == x.w) {
/* x.w使用卫星电话,代价是0,ans取比x.w小的 \
里面最大的 */
ans = pq.top().w;
}
// pq.pop();
// ans = pq.top().w;
}
}
int main() {
/* 初始化并查集 */
init();
/* 输入 */
cin >> s >> p;
double x, y;
a.push_back({ 0, 0 });
for (int i = 1; i <= p; i++) {
cin >> x >> y;
a.push_back({ x, y });
}
/* 建边(每两个节点都要建) */
for (int i = 1; i <= p; i++) {
for (int j = i + 1; j <= p; j++) {
if (i == j) {
continue;
}
edge.push_back({ i, j, dis(i, j) });
}
}
/* 计算最小生成树 */
kruscal();
/* 输出答案(保留2位小数) */
cout << fixed << setprecision(2) << ans;
return 0;
}
后来在同学的见一下,将一大堆复杂的逻辑改成删s-1条边,就A了
CPP#include <cmath>
#include <queue>
#include <vector>
#include <bitset>
#include <climits>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define debug(x) (cerr << x << '\n')
using namespace std;
const int N = 505;
int s, p;
double ans = 0.0;
vector<int> fa(N);
bitset<N> hasPhone; /* 判断哨所是否有卫星电话 */
struct Node {
double x;
double y;
};
vector<Node> a;
struct Edge {
int from;
int to;
double w;
bool operator < (const Edge& a) const {
return w < a.w;
}
};
vector<Edge> edge;
inline void init() {
for (int i = 0; i < N; i++) {
fa[i] = i;
}
}
inline double dis(const int& i1, const int& i2) {
/* 哨所距离 */
return sqrt(pow(abs(a[i1].x - a[i2].x), 2) + \
pow(abs(a[i1].y - a[i2].y), 2));
}
inline int find(const int& u) {
return fa[u] == u ? u : fa[u] = find(fa[u]);
}
void kruscal() {
priority_queue<Edge> pq; /* 存用过的最大的边 */
sort(edge.begin(), edge.end());
/* for循环结束后ans为最长边 */
for (auto x : edge) {
if (find(x.from) == find(x.to)) {
continue;
}
fa[find(x.from)] = find(x.to);
ans = x.w;
pq.push(x);
}
for (int i = 1; i <= s - 1; i++) {
// while (s > 0) {
// /* 目前边权最大的边 */
// Edge x = pq.top();
// pq.pop();
// /* 如果起点没有卫星电话 */
// if (!hasPhone[x.from]) {
// /* 判断剩的卫星电话够不够用 */
// if (s < 1) {
// break;
// } else {
// /* 给起点安装卫星电话 */
// s--;
// hasPhone[x.from] = true;
// }
// }
// /* 如果终点没有卫星电话 */
// if (!hasPhone[x.to]) {
// /* 判断剩的卫星电话够不够用 */
// if (s < 1) {
// break;
// } else {
// /* 给终点安装卫星电话 */
// s--;
// hasPhone[x.to] = true;
// }
// }
// /* 如果ans是当前处理的值 */
// if (ans == x.w) {
// /* x.w使用卫星电话,代价是0,ans取比x.w小的 \
// 里面最大的 */
// ans = pq.top().w;
// }
pq.pop();
ans = pq.top().w;
}
}
int main() {
/* 初始化并查集 */
init();
/* 输入 */
cin >> s >> p;
double x, y;
a.push_back({ 0, 0 });
for (int i = 1; i <= p; i++) {
cin >> x >> y;
a.push_back({ x, y });
}
/* 建边(每两个节点都要建) */
for (int i = 1; i <= p; i++) {
for (int j = i + 1; j <= p; j++) {
if (i == j) {
continue;
}
edge.push_back({ i, j, dis(i, j) });
}
}
/* 计算最小生成树 */
kruscal();
/* 输出答案(保留2位小数) */
cout << fixed << setprecision(2) << ans;
return 0;
}
请问为什么一定删s - 1条边
谢谢
回复
共 4 条回复,欢迎继续交流。
正在加载回复...