ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Kruskal算法求最小生成树

2022-06-22 20:35:25  阅读:135  来源: 互联网

标签:int Kruskal 最小 生成 edge1 算法 include


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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有