Kruskal算法求最小生成树

143 阅读1分钟

Kruskal算法首先将所有边权从小到大排序,循环枚举边,若该边的端点ab不连通,则将ab边加入集合中去。判断是否连通的方法使用并查集

题目思路

  1. 将边权进行从小到大排序,因为要求最小生成树,确保最小权值。
  2. 初始化并查集,p[i] = i
  3. 循环m条边,使用并查集判断a和b是否连通,若不连通,则将ab边加入集合中去,记录权值。
  4. 使用cnt记录加入的点的数量,若小于n-1,则点没有找全,最小生成树不存在;否则输出结果。

C++代码

#include<iostream>
#include<algorithm>

using namespace std;

const int M = 200010;

int n, m;
int p[M];

struct Edge
{
    int a, b, w;

    bool operator < (const Edge& W) const
    {
        return w < W.w;
    }
}edge[M];

int find(int x)
{
    if (p[x] != x)
    {
        p[x] = find(p[x]);
    }
    return p[x];
}

void Kruskal()
{
    sort(edge, edge + m);

    for (int i = 1; i <= n; i++)
    {
        p[i] = i;
    }

    int res = 0, cnt = 0;
    for (int i = 0; i < m; i++)
    {
        int a = edge[i].a;
        int b = edge[i].b;
        int w = edge[i].w;

        a = find(a), b = find(b);
        if (a != b)
        {
            p[a] = b;
            res += w;
            cnt++;
        }
    }

    if (cnt < n - 1)
    {
        cout << "impossible";
    }
    else
    {
        cout << res;
    }

}

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    cin >> n >> m;
    for (int i = 0; i < m; i++)
    {
        int a, b, w;
        cin >> a >> b >> w;
        edge[i] = { a,b,w };
    }

    Kruskal();

    return 0;
}