📅  最后修改于: 2023-12-03 15:37:18.518000             🧑  作者: Mango
Kruskal 算法是一种常用的求解最小生成树的算法。其基本思路是先将所有边按照权值从小到大排序,然后逐一加入到生成树中,但要保证加入的边不构成环。具体实现中,可以使用并查集等数据结构来维护连通性。在 C++ 中,使用 STL 提供的数据结构可以轻松实现 Kruskal 的最小生成树算法。
以下是 Kruskal 的最小生成树的 C++ 实现:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
struct Edge {
int u, v, w;
Edge(int u, int v, int w) : u(u), v(v), w(w) {}
};
struct UnionFind {
vector<int> parent, rank;
UnionFind(int n) : parent(n), rank(n, 1) {
for (int i = 0; i < n; ++i) {
parent[i] = i;
}
}
int find(int x) {
if (parent[x] != x) parent[x] = find(parent[x]);
return parent[x];
}
bool merge(int x, int y) {
int px = find(x), py = find(y);
if (px == py) return false;
if (rank[px] < rank[py]) swap(px, py);
parent[py] = px;
rank[px] += rank[py];
return true;
}
};
vector<Edge> kruskal(int n, vector<Edge>& edges) {
sort(edges.begin(), edges.end(), [](const Edge& e1, const Edge& e2) {
return e1.w < e2.w;
});
UnionFind uf(n);
vector<Edge> res;
for (auto& e : edges) {
if (uf.merge(e.u, e.v)) {
res.push_back(e);
if (res.size() == n - 1) break;
}
}
return res;
}
int main() {
int n, m;
cin >> n >> m;
vector<Edge> edges;
for (int i = 0; i < m; ++i) {
int u, v, w;
cin >> u >> v >> w;
edges.emplace_back(u - 1, v - 1, w);
}
auto res = kruskal(n, edges);
int sum = 0;
for (auto& e : res) {
sum += e.w;
}
cout << sum << endl;
return 0;
}
这段代码中,首先定义了一个 Edge
结构体来存储边的信息,包括起点、终点和权值。另外,定义了一个 UnionFind
类,用来实现并查集的相关操作,如并查集的初始化、查找操作和合并操作。
在 kruskal
函数中,首先将所有边按照权值从小到大排序,然后逐一加入到生成树中,当加入一条边后,如果该边的两个端点不在同一个连通块中,则将它们合并,同时将该边加入到最小生成树中。最后返回构成最小生成树的边的集合。
在 main
函数中,首先读入输入的数据,然后调用 kruskal
函数,得到最小生成树的边的集合。最后计算所有边的权值和并输出。
本实现中使用了 C++ 中的 Lambda 表达式,可以方便的比较两条边的权值大小。使用了 vector 存储边的集合,并查集使用了 vector 和 rank 数组来实现。此外,程序还使用了 STL 中的一些常用函数和数据结构,如sort
函数等。
综上所述,使用 STL 的 Kruskal 的最小生成树算法能够快速、高效地求解最小生成树问题。它具有实现简单、易于理解、维护方便等优点。