diff --git a/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1145.cpp b/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1145.cpp index 3563d50..ffd27df 100644 --- a/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1145.cpp +++ b/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1145.cpp @@ -5,19 +5,16 @@ typedef pair 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); diff --git a/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1145.md b/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1145.md index 82e970b..8f7bf4e 100644 --- a/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1145.md +++ b/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1145.md @@ -62,9 +62,9 @@ $1≤n≤500,0≤x,y≤10^4,0≤k≤100$ 而题目的要求是: 找到满足连通块个数不超过$k$个的最小的$d$ -本质上就是对$Kruskal$算法的 **魔改** 一下,考虑$Kruskal$的计算过程: +本质上就是对$Kruskal$算法的 **魔改** ,考虑$Kruskal$的计算过程: -按照边权递增的顺序, 当把两个不连通的顶点连通时, 相当于在图中减少了一个连通块. 在连通块恰好减少到$k$时, 对应的边权因为有递增的保证, 所以是满足条件的最小边权 +按照边权递增的顺序, 当把两个不连通的顶点连通时, 相当于在图中减少了一个连通块, 在连通块恰好减少到$k$时, 对应的边权因为有递增的保证, 所以是满足条件的最小边权。 ```cpp {.line-numbers} #include @@ -74,19 +74,16 @@ typedef pair 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; } + ```