859. Kruskal算法求最小生成树

发布时间:2022-07-04 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了859. Kruskal算法求最小生成树脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

题目传送门

理解与感悟

⭐️ 1、克鲁斯卡尔算法的基本思想是以边为主导地位 始终选择当前可用的最小边权的边(可以直接快排或者algorIThm的sort)。每次选择边权最小的边链接两个端点是kruskal的规则,并实时判断两个点之间有没有间接联通。

⭐️ 2、PRim算法适合稠密图,kruskal算法适合稀疏图。 理由也挺简单的,Kruskal是按边存的,边少就合适,边多就不适合。稀疏图当然边少,稠密图是点少,但边多,边可能达到节点数的平方,即每个节点都与其它节点有边。

⭐️ 3、基本思路:

(1) 将所有边按权重从小到大排序。

(2) 枚举每条边 a-b,

    if a,b 不连通:
        将这条边加入集合中
    结束  

现在我来模拟一下:

假如有以下几个城市,之间都有相连的道路:

859. Kruskal算法求最小生成树

根据kruskal的原理,我们需要对边权dis进行排序,每次找出最小的边。 排序后,最小的边自然是第8条边,于是4和6相连。

859. Kruskal算法求最小生成树

遍历继续,第二小的边是1号,1和2联通。

859. Kruskal算法求最小生成树

再后来是边3连接1,4。

859. Kruskal算法求最小生成树

dis也是14的还有边5,它连接3,4。

859. Kruskal算法求最小生成树

其次是dis为15的边4,但是2和4已经相连了,pass。 然后是dis为16的两条边(边2和边9),边2连接1和3,边9连接3和6,它们都已经间接相连,pass。 再然后就是dis为22的边10,它连接5和6,5还没有加入组织,所以使用这边。继续,发现此时已经连接了n-1条边,结束,最后图示如下:

859. Kruskal算法求最小生成树

本题与 https://www.acwing.COM/problem/content/839/ 是姊妹题,其实Kruskal算法就是一个并查集的应用。

不像Prim算法,不用考虑边界,考虑循环N次啊,计算最小值啊,还要用堆进行优化啊,这个就是一个并查集,思路简单。

需要回答的问题

Q:只需要简单结构体即可,不需要邻接表或者邻接矩阵来存,为什么呢? A:之所以使用邻接表或邻接矩阵,其实说白了,是按点存的,记录A点和B点的关系。 用结构体存储,其实是按边存的,就是题目说有一条A-B的边(权为C),我们就存了一个A-B权为C的边。 按点存麻烦(邻接表或邻接矩阵),按边存(结构体数组)简单。

C++ 代码

#include <iostream>
#include <algorithm>
using namespace std;

const int N = 200010;

int n, m;
int p[N]; //并查集里面的p数组

struct Edge {
    int a, b, w;
    // 需要重载<号,利用w 进行排序
    //这里重载小于号的目的是因为能用<号表示的数据才能够用标准库sort排序
    bool operator<(const Edge &amp;W) const {
        return w < W.w;
    }
} edges[N];

//并查集模板
int find(int x) {
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}
int main() {
    scanf("%d%d", &n, &;m);

    for (int i = 0; i < m; i++) {
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        edges[i] = {a, b, w};
    }
    
    //利用STL进行快速排序
    sort(edges, edges + 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 = edges[i].a, b = edges[i].b, w = edges[i].w;
        //找祖宗
        a = find(a), b = find(b);
        //如果两个节点不连通,判断祖宗节点是不是一样的
        if (a != b) {
            p[a] = b;   //a认b为祖宗,合并两个集合
            res += w;   //最小生成树中所有树边的权重之和
            cnt++;      //加入了多少条边
        }
    }
    //如果加入的边数小于n-1(抽屉原理),说明不连通,连通图也有最小生成树,不连通没有
    if (cnt < n - 1) puts("impossible");
    else printf("%dn", res);

    return 0;
}

脚本宝典总结

以上是脚本宝典为你收集整理的859. Kruskal算法求最小生成树全部内容,希望文章能够帮你解决859. Kruskal算法求最小生成树所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。