编程语言
首页 > 编程语言> > Kruskal算法求最小生成树

Kruskal算法求最小生成树

作者:互联网

c++

Kruskal算法求最小生成树

/*
 * 最小生成树
 * 最小生成树是图论中最为常见的问题之一,不过相比于最短路中的单源最短路和多源最短路,最小生成树算法主流仅有两种。
 * 分别是 Prim 算法和 Kruskal 算法。这两个算法一个是基于点的算法,一个是基于边的算法。
 * 这两者的关系有些像 最短路中 Dijkstra 和 Bellmanford。其中,Prim 算法和 Dijkstra 的流程图几乎一致。
 * 此次,我们将要介绍著名的 Kruskal 算法。
 *
 * 算法流程:
 *      Step 1:
 *          将所有的边按照边权大小从小到大排序。
 *      Step 2:
 *          按照从小到大的顺序遍历所有的边,对每一个边 edge 的端点 u, v,倘若 u v 不在一个连通域内,那么就将 u v相连。
 *      Step 3:
 *          倘若最后,所有的点都进入了同一个连通域,那么最小生成树构成。否则,最小生成树不存在。
 * 算法证明:
 *      对于这种迭代算法,仅需要证明其在 for 循环中,算法仍然成立即可。
 *      假如说,我们边为 edge1 时候,u v 端点不在同一个连通域中,不妨考虑,有没有一种可能,不加入 edge1 使得 u v相连通了呢?
 *
 *      假如说,有一种解决方案,得到了最小生成树,并没有用到 edge1。但是从我们排序边这个做法可以知道,edge1 绝对是 连接 u, v代价最小的办法。
 *      因此将 edge1 放到这个最小生成树中,必定可以找到环中 大于等于 edge1 权重的边,将其拿下,还是最小生成树。
 *      不断迭代,可以说明,我们这样是对的。
 *
 * 算法复杂度:
 *      算法主要复杂度是对边的排序,算法复杂度为 M log M
 * 注意点:
 *      这是无向图,排序和并查集
 */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>

using namespace std;

const int N = 100010, M = 200010, INF = 0x3f3f3f3f;

class Edge {
public:
    int u, v, w;
};
Edge e[M];
int n, m;
int fa[N];

bool cmp(Edge t1, Edge t2) {
    return t1.w < t2.w;
}

int Find(int x) {
    if (fa[x] == x) {
        return x;
    } else {
        return fa[x] = Find(fa[x]);
    }
}


void Union(int x, int y) {
    x = Find(x), y = Find(y);
    fa[x] = y;
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1, a, b, c; i <= m; i ++ ) {
        scanf("%d%d%d", &a, &b, &c);
        e[i].u = a, e[i].v = b, e[i].w = c;
    }

    sort(e + 1, e + m + 1, cmp);

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

    int ret = 0, cnt = 0;
    for (int i = 1; i <= m; i ++ ) {
        if (Find(e[i].u) == Find(e[i].v)) {
            continue;
        } else {
            Union(e[i].u, e[i].v);
            ret += e[i].w;
            cnt += 1;
        }
    }

    if (cnt == n - 1) {
        printf("%d\n", ret);
    } else {
        printf("impossible\n");
    };
    return 0;
}

标签:int,Kruskal,最小,生成,edge1,算法,include
来源: https://www.cnblogs.com/lucky-light/p/16402163.html