diff --git a/TangDou/AcWing/MinimalSpanningTree/858.cpp b/TangDou/AcWing/MinimalSpanningTree/858.cpp index f834f03..4be1e06 100644 --- a/TangDou/AcWing/MinimalSpanningTree/858.cpp +++ b/TangDou/AcWing/MinimalSpanningTree/858.cpp @@ -12,6 +12,10 @@ int res; // 最小生成树里面边的长度之和 // 普利姆算法求最小生成树 int prim() { + // 距离初始化无穷大,表示所有结点都在生成树之外 + memset(dis, 0x3f, sizeof dis); + dis[1] = 0; + for (int i = 0; i < n; i++) { // 迭代n次 /* 1、找到集合外,距离集合最近的点,记为t,此时有两种情况进行猴子选大王: @@ -48,8 +52,7 @@ int main() { cin >> n >> m; // 所有点之间的距离初始化为正无穷,然后再读入所有边 memset(g, 0x3f, sizeof g); - // 距离初始化无穷大,表示所有结点都在生成树之外 - memset(dis, 0x3f, sizeof dis); + // 读入数据 while (m--) { int a, b, c; diff --git a/TangDou/AcWing/MinimalSpanningTree/858.md b/TangDou/AcWing/MinimalSpanningTree/858.md index a8e727d..f10a0d0 100644 --- a/TangDou/AcWing/MinimalSpanningTree/858.md +++ b/TangDou/AcWing/MinimalSpanningTree/858.md @@ -137,6 +137,10 @@ int res; // 最小生成树里面边的长度之和 // 普利姆算法求最小生成树 int prim() { + // 距离初始化无穷大,表示所有结点都在生成树之外 + memset(dis, 0x3f, sizeof dis); + dis[1] = 0; + for (int i = 0; i < n; i++) { // 迭代n次 /* 1、找到集合外,距离集合最近的点,记为t,此时有两种情况进行猴子选大王: @@ -150,7 +154,7 @@ int prim() { /*2、如果不是第一个点,并且剩余的点距离集合的最小距离是INF,说明现在没有点可以连通到生成树, 这时不是连通图,没有最小生成树,返回INF - 如果是第一个点,因为把它加到集合中去的代码是在下面进行的,此时它也没有被加入到集合中去,所以dis[t]=INF,这时不能说无解 + 如果是第一个点,因为把它加到集合中去的代码是在下面进行的,此时它也没有被加入到集合中去,所以dist[t]=INF,这时不能说无解 因为才刚刚开始,需要特判一下 */ if (i && dis[t] == INF) return INF; @@ -173,8 +177,7 @@ int main() { cin >> n >> m; // 所有点之间的距离初始化为正无穷,然后再读入所有边 memset(g, 0x3f, sizeof g); - // 距离初始化无穷大,表示所有结点都在生成树之外 - memset(dis, 0x3f, sizeof dis); + // 读入数据 while (m--) { int a, b, c; @@ -211,6 +214,10 @@ int pre[N]; // 前驱结点 // 普利姆算法求最小生成树 int prim() { + memset(dis, 0x3f, sizeof dis); + memset(pre, -1, sizeof pre); // 记录前驱路径 + dis[1] = 0; + for (int i = 0; i < n; i++) { // 迭代n次 int t = -1; for (int j = 1; j <= n; j++) @@ -230,8 +237,6 @@ int prim() { int main() { cin >> n >> m; memset(g, 0x3f, sizeof g); - memset(dis, 0x3f, sizeof dis); - memset(pre, -1, sizeof pre); // 记录前驱路径 // 读入数据 while (m--) { diff --git a/TangDou/AcWing/MinimalSpanningTree/858_WithPath.cpp b/TangDou/AcWing/MinimalSpanningTree/858_WithPath.cpp index 1b7203e..e935ef1 100644 --- a/TangDou/AcWing/MinimalSpanningTree/858_WithPath.cpp +++ b/TangDou/AcWing/MinimalSpanningTree/858_WithPath.cpp @@ -13,6 +13,10 @@ int pre[N]; // 前驱结点 // 普利姆算法求最小生成树 int prim() { + memset(dis, 0x3f, sizeof dis); + memset(pre, -1, sizeof pre); // 记录前驱路径 + dis[1] = 0; + for (int i = 0; i < n; i++) { // 迭代n次 int t = -1; for (int j = 1; j <= n; j++) @@ -32,8 +36,6 @@ int prim() { int main() { cin >> n >> m; memset(g, 0x3f, sizeof g); - memset(dis, 0x3f, sizeof dis); - memset(pre, -1, sizeof pre); // 记录前驱路径 // 读入数据 while (m--) { diff --git a/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1141.eddx b/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1141.eddx new file mode 100644 index 0000000..75fa7f0 Binary files /dev/null and b/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1141.eddx differ diff --git a/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1142.md b/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1142.md index 12535f9..a8bf76f 100644 --- a/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1142.md +++ b/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1142.md @@ -36,13 +36,14 @@ using namespace std; const int N = 310, M = 8010; -// 记录边的结构体 -struct Edge { - int a, b, w; - const bool operator<(const Edge &t) const { - return w < t.w; + +// Kruskal用到的结构体 +struct Node { + int a, b, c; + bool const operator<(const Node &t) const { + return c < t.c; // 边权小的在前 } -} e[M]; +} edge[M]; int n, m; int p[N]; @@ -52,26 +53,32 @@ int find(int x) { return p[x]; } +int res; + +// Kruskal算法 +void kruskal() { + // 1、按边权由小到大排序 + sort(edge, edge + m); + // 2、并查集初始化 + for (int i = 1; i <= n; i++) p[i] = i; + // 3、迭代m次 + for (int i = 0; i < m; i++) { + int a = edge[i].a, b = edge[i].b, c = edge[i].c; + a = find(a), b = find(b); + if (a != b) + p[a] = b, res = c; // 越往后越大 + } +} + int main() { cin >> n >> m; - for (int i = 1; i <= n; i++) p[i] = i; // 并查集初始化 for (int i = 0; i < m; i++) { int a, b, c; cin >> a >> b >> c; - e[i] = {a, b, c}; - } - // 排序(按边权) - sort(e, e + m); - - int res = 0; - for (int i = 0; i < m; i++) { - int a = find(e[i].a), b = find(e[i].b), w = e[i].w; - if (a != b) { - p[a] = b; - res = w; // 越往后越大 - } + edge[i] = {a, b, c}; } + kruskal(); printf("%d %d\n", n - 1, res); return 0; } @@ -83,25 +90,26 @@ int main() { using namespace std; const int N = 310; -int dist[N]; +int dis[N]; int g[N][N]; int n, m; bool st[N]; int prim() { - memset(dist, 0x3f, sizeof dist); - dist[1] = 0; + memset(dis, 0x3f, sizeof dis); + dis[1] = 0; int res = 0; for (int i = 0; i < n; i++) { int t = -1; for (int j = 1; j <= n; j++) - if (!st[j] && (t == -1 || dist[t] > dist[j])) + if (!st[j] && (t == -1 || dis[t] > dis[j])) t = j; - st[t] = true; - res = max(res, dist[t]); // 找出最长,不要累加和 + res = max(res, dis[t]); // 找出最长,不要累加和 for (int j = 1; j <= n; j++) - dist[j] = min(dist[j], g[t][j]); + if (!st[j] && dis[j] > g[t][j]) + dis[j] = g[t][j]; + st[t] = true; } return res; } diff --git a/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1142_Kruskal.cpp b/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1142_Kruskal.cpp index 76387a4..7b98cd0 100644 --- a/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1142_Kruskal.cpp +++ b/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1142_Kruskal.cpp @@ -2,13 +2,14 @@ using namespace std; const int N = 310, M = 8010; -// 记录边的结构体 -struct Edge { - int a, b, w; - const bool operator<(const Edge &t) const { - return w < t.w; + +// Kruskal用到的结构体 +struct Node { + int a, b, c; + bool const operator<(const Node &t) const { + return c < t.c; // 边权小的在前 } -} e[M]; +} edge[M]; int n, m; int p[N]; @@ -18,26 +19,32 @@ int find(int x) { return p[x]; } +int res; + +// Kruskal算法 +void kruskal() { + // 1、按边权由小到大排序 + sort(edge, edge + m); + // 2、并查集初始化 + for (int i = 1; i <= n; i++) p[i] = i; + // 3、迭代m次 + for (int i = 0; i < m; i++) { + int a = edge[i].a, b = edge[i].b, c = edge[i].c; + a = find(a), b = find(b); + if (a != b) + p[a] = b, res = c; // 越往后越大 + } +} + int main() { cin >> n >> m; - for (int i = 1; i <= n; i++) p[i] = i; // 并查集初始化 for (int i = 0; i < m; i++) { int a, b, c; cin >> a >> b >> c; - e[i] = {a, b, c}; - } - // 排序(按边权) - sort(e, e + m); - - int res = 0; - for (int i = 0; i < m; i++) { - int a = find(e[i].a), b = find(e[i].b), w = e[i].w; - if (a != b) { - p[a] = b; - res = w; // 越往后越大 - } + edge[i] = {a, b, c}; } + kruskal(); printf("%d %d\n", n - 1, res); return 0; } \ No newline at end of file diff --git a/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1142_Prim.cpp b/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1142_Prim.cpp index 2cdf756..ab94bcb 100644 --- a/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1142_Prim.cpp +++ b/TangDou/AcWing_TiGao/T3/MinialSpanningTree/1142_Prim.cpp @@ -2,25 +2,26 @@ using namespace std; const int N = 310; -int dist[N]; +int dis[N]; int g[N][N]; int n, m; bool st[N]; int prim() { - memset(dist, 0x3f, sizeof dist); - dist[1] = 0; + memset(dis, 0x3f, sizeof dis); + dis[1] = 0; int res = 0; for (int i = 0; i < n; i++) { int t = -1; for (int j = 1; j <= n; j++) - if (!st[j] && (t == -1 || dist[t] > dist[j])) + if (!st[j] && (t == -1 || dis[t] > dis[j])) t = j; - st[t] = true; - res = max(res, dist[t]); // 找出最长,不要累加和 + res = max(res, dis[t]); // 找出最长,不要累加和 for (int j = 1; j <= n; j++) - dist[j] = min(dist[j], g[t][j]); + if (!st[j] && dis[j] > g[t][j]) + dis[j] = g[t][j]; + st[t] = true; } return res; } diff --git a/TangDou/Topic/【最小生成树】专题.md b/TangDou/Topic/【最小生成树】专题.md index 83f5faf..06ad61e 100644 --- a/TangDou/Topic/【最小生成树】专题.md +++ b/TangDou/Topic/【最小生成树】专题.md @@ -143,7 +143,9 @@ $Prim$或者$Kruskal$祼题,直接套模板即可 #### [$AcWing$ $1141$. 局域网](https://www.cnblogs.com/littlehb/p/16044103.html) 最小生成森林,需要注意与最小生成树的区别,两种方法,推荐使用$Kruskal$ -AcWing 1142. 繁忙的都市 +#### [$AcWing$ $1142$. 繁忙的都市](https://www.cnblogs.com/littlehb/p/16044984.html) + + AcWing 1143. 联络员 AcWing 1144. 连接格点