• 最小生成树算法Kruskal详解


    要讲Kruskal,我们先来看下面一组样例。

    4 5
    1 2 3
    1 4 5
    2 4 7
    2 3 6
    3 4 8
    14

      

    画出来更直观一些,就是上面的这张图。

    智商只要不是0的(了解最小生成树是什么的童鞋)应该都知道要选择1<->4, 1<->2, 2<->3三条边那么大家就会问为什么选择这三条呢。

    一棵树边的数量等于这棵输的点的数量减1。(不信自己画画试试)这里不再解释。

    假设有N个点,那么我们肯定要选择n-1条边来生成一棵树。这棵树就是这张图的生成树。

    很显然生成树有一堆。

    而最小生成树是指边权之和最小的生成树。那么我们自然而然的想到了贪心!!!

    没错,就是贪心,我们按照边的权值进行贪心。

    同时为了保证到最后所有的点都连在了一起,并且没有多余的边。我们就要用到并查集。只要两个顶点被一条边所连接。那么他们就有一个共同的祖先。我们在以后就只要判断一下,只要两个顶点没有共同祖先,就可以将他们连入生成树中。当边的条数加到n-1时,我们就可以结束了。

    下面是代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    int n, m;
    int f[100008];
    int sum, tot;
    struct edge{
        int u, v, w;
    }ed[1000008];
    
    bool cmp(edge a, edge b) {
        return a.w < b.w;
    }
    
    int find(int x) {
        if(x == f[x]) return x;
        else return f[x] = find(f[x]);
    }
    
    int main() {
        scanf("%d%d", &n, &m);
        for(int i=1; i<=n; i++) {
            f[i] = i;
        }
        for(int i=1; i<=m; i++) {
            scanf("%d%d%d", &ed[i].u, &ed[i].v, &ed[i].w);
        }
        sort(ed+1, ed+1+m, cmp);
        for(int i=1; i<=m; i++) {
            int xx = find(ed[i].u), yy = find(ed[i].v);
            if(xx != yy) {
                f[xx] = find(yy);
                tot++;
                sum += ed[i].w;
            }
            if(tot == n-1) {
                break;
            }
        }
        printf("%d", sum);
    }
    作者:wlz
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    JDBC——java连接操作数据库的步骤
    JVM——编译和运行
    base——运算符的用法
    JVM——类的初始化【转】
    JVM——类加载机制
    base——gc方法与finalize方法的区别
    JVM——垃圾回收机制&&jvm内存分配机制
    JVM——虚拟机的简介【摘录】
    2019-06-12_java.lang.RuntimeException: Serialized class com.taotao.common.pojo.SearchItem must implement java.io.Serializable
    2019-06-12_Python-Break语句
  • 原文地址:https://www.cnblogs.com/bljfy/p/8728133.html
Copyright © 2020-2023  润新知