main
黄海 2 years ago
parent 15237e4b42
commit 8f741f5259

@ -5,19 +5,16 @@ 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;
const int N = 510, M = N * N;
int n, k;
struct Edge {
int a, b;
double w;
double c;
const bool operator<(const Edge &t) const {
return w < t.w;
return c < t.c;
}
} e[M];
} edge[M];
int el;
// 每个村庄的坐标
@ -43,11 +40,10 @@ int main() {
// 枚举所有点与点之间的边
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])};
edge[el++] = {i, j, get_dist(q[i], q[j])}; // 记录单向边即可
// 边权由小到大排序
sort(e, e + el);
sort(edge, edge + el);
// 并查集初始化
for (int i = 0; i < n; i++) p[i] = i;
@ -61,11 +57,13 @@ int main() {
// 给原图的节点中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);
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;
cnt--; // 连通块数量-1
res = e[i].w; // 不停的记录参数d的上限
res = c; // 不停的记录参数d的上限
cnt--; // 连通块数量-1
}
}
printf("%.2lf\n", res);

@ -62,9 +62,9 @@ $1≤n≤500,0≤x,y≤10^4,0≤k≤100$
而题目的要求是: <font color='red' size=4><b>找到满足连通块个数不超过$k$个的最小的$d$</b></font>
本质上就是对$Kruskal$算法的 **魔改** 一下,考虑$Kruskal$的计算过程:
本质上就是对$Kruskal$算法的 **魔改** ,考虑$Kruskal$的计算过程:
按照边权递增的顺序, 当把两个不连通的顶点连通时, 相当于在图中减少了一个连通块. 在连通块恰好减少到$k$时, 对应的边权因为有递增的保证, 所以是满足条件的最小边权
按照边权递增的顺序, 当把两个不连通的顶点连通时, 相当于在图中减少了一个连通块, 在连通块恰好减少到$k$时, 对应的边权因为有递增的保证, 所以是满足条件的最小边权
```cpp {.line-numbers}
#include <bits/stdc++.h>
@ -74,19 +74,16 @@ 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;
const int N = 510, M = N * N;
int n, k;
struct Edge {
int a, b;
double w;
double c;
const bool operator<(const Edge &t) const {
return w < t.w;
return c < t.c;
}
} e[M];
} edge[M];
int el;
// 每个村庄的坐标
@ -112,11 +109,10 @@ int main() {
// 枚举所有点与点之间的边
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])};
edge[el++] = {i, j, get_dist(q[i], q[j])}; // 记录单向边即可
// 边权由小到大排序
sort(e, e + el);
sort(edge, edge + el);
// 并查集初始化
for (int i = 0; i < n; i++) p[i] = i;
@ -130,15 +126,18 @@ int main() {
// 给原图的节点中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);
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;
cnt--; // 连通块数量-1
res = e[i].w; // 不停的记录参数d的上限
res = c; // 不停的记录参数d的上限
cnt--; // 连通块数量-1
}
}
printf("%.2lf\n", res);
return 0;
}
```

Loading…
Cancel
Save