$Kruskal$ 算法的实现 | 最小生成树

\(Kruskal\) 算法

Luogu P3366 为例题

实现方法:从小到大遍历每一条线,如果该线连接的两点已经都在树内则不处理,否则描出这条线

从小到大是一个贪心的实现方法,由于每描出一条线,就会生成一棵新的树或将一个点加入一棵树中。第一个点不需要连线处理,因此描出这棵树所需要的边的数量一定是这棵树的点的数量减一(也许树本身就存在这样的性质?)

当然,有一个例外,那就是给出的图不连通

我们暂时不用考虑图的连通性的问题,因为例题给出的要求是:对于所有不连通的图,输出 orz

使用并查集维护该树

示例代码:

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 5;

pair<int, pair<int, int>> g[N];  // The weight on the line between Point A and Point B, Point A, Point B

int fa[N];  // Father Point

int f(int x) {  // Finding Point X's Extra Grandpa
    if (fa[x] == x) return x;
    return fa[x] = f(fa[x]);  // Disjoint Set Union path compression
}

int main() {
    int m, n;
    cin >> n >> m;
    for (int i = 1, u, v, w; i <= m; i++)  // Saving
        cin >> u >> v >> w,
        g[i].first = w,
        g[i].second.first = u,
        g[i].second.second = v;
    for (int i = 1; i <= n; i++) fa[i] = i;  // Initialize All Points' Father as themselves
    sort(g + 1, g + m + 1);
    int ans = 0, cnt = 0;  // Use cnt to make sure that all point was connected
    for (int i = 1; i <= m; i++) {
        int u = g[i].second.first, v = g[i].second.second, w = g[i].first;  // Reading
        if (f(u) == f(v)) continue;  // Had been connected
        ans += w, fa[f(v)] = fa[u], cnt++;  // Add the weight, connect Point V and Point U
    }
    if (cnt == n - 1) cout << ans << endl;  // If there's n points, then there will be connecting for n - 1 times
    else cout << "orz" << endl;  // Some points didn't connected
    return 0;
}
posted @ 2024-06-02 10:37  Bramble_Marshall  阅读(50)  评论(0)    收藏  举报