📜  在 C++ 中使用 STL 的 Kruskal 的最小生成树(1)

📅  最后修改于: 2023-12-03 15:37:18.518000             🧑  作者: Mango

在 C++ 中使用 STL 的 Kruskal 的最小生成树

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 的最小生成树算法能够快速、高效地求解最小生成树问题。它具有实现简单、易于理解、维护方便等优点。