zoukankan      html  css  js  c++  java
  • Kruskal算法

    Kruskal算法(克鲁斯卡尔算法)

    核心操作
    1、将所有边按权重大小 从小到大排序 O(mlogm); 这部分是本算法的瓶颈 比较耗时
    2、 枚举每条边a -b 权重为c
    如果 a-b 不连通 则把这条边加入集合中
    (因为最小生成树不能含有自环,如果a-b已经连通,再加入这条边就会形成自环)

    并查集的操作来维护本算法

    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 100010, M = 200010, INF = 0x3f3f3f3f;
    
    int n, m;
    int p[N];
    
    struct Edge
    {
        int a, b, w;
    
        /* bool operator< (const Edge &W)const
         {
            return w < W.w;
         }*/
        Edge() {
    
            a = 0;
            b = 0;        //注意 ,当写了有参构造函数时,一定要加上无参构造函数,不然会编译出错
            w = 0;
    
        }
        Edge(int aa, int bb, int ww) {
            a = aa;
            b = bb;
            w = ww;
        }
    
    }edges[M];
    
    bool operator<(Edge A, Edge B) {
    
        return A.w < B.w;          //重载运算符 使用sort排序时一般重载小于号
    }
    
    int find(int x)
    {
        if (p[x] != x) p[x] = find(p[x]); //并查集中的find函数
        return p[x];                    // 如果x不是祖宗节点 则继续找祖宗节点 否则返回祖宗节点
    }
    
    int kruskal()
    {
        sort(edges+1, edges + m+1);//注意 数组为1~m排序时  sort正常是0~n
    
        for (int i = 1; i <= n; i++) p[i] = i;    // 初始化并查集
    
        int res = 0, cnt = 0;
        for (int i = 1; i <=m; i++)
        {
            int a = edges[i].a, b = edges[i].b, w = edges[i].w;
    
            a = find(a), b = find(b);//找到a b的祖宗节点
            if (a != b)//如果祖宗节点不同 则说明他们不连通
            {
                p[a] = b; //将他们合并成一个集合
                res += w;//累加边的权重值
                cnt++;//更新集合中已经有的边数
            }
        }
    
        if (cnt < n - 1) return INF;//n个点 一共有n-1 条边 如果最后集合中的边数小于n-1 则说明不能连通
        return res;// 图可以连通 返回边权和
    }
    
    int main()
    {
        scanf("%d%d", &n, &m);
    
        for (int i = 1; i <=m; i++)  //结构体无向图初始化方法 本体按有向图初始化不影响最小生成树
        {
            int a, b, w;
            scanf("%d%d%d", &a, &b, &w);
            edges[i] = Edge(a, b, w);
    
        }
    
        int t = kruskal();
    
        if (t == INF) puts("impossible");
        else printf("%d
    ", t);
    
        return 0;
    }
    
    你以为的极限,也许只是别人的起点
  • 相关阅读:
    编写测试类实现并发访问固定URL(亲测能用!!!)
    java项目添加log4j打印日志+转换系统时间
    springboot项目没错,但就是报红叉
    我想查看数据库名,输入命令:select name from v$database;为什么会说表和视图不存在
    DRUID连接池的实用 配置详解+使用方法+监控方式(太强大了!!!)
    Druid连接池 属性说明
    springBoot2.2.0+mybatis-xml文件方式+Oracle11g+jsp页面,实现简单的CRUD
    s5-12 RIP
    s5-12 RIP
    s5-13 RIP 为什么会 衰败
  • 原文地址:https://www.cnblogs.com/LengDing/p/14296866.html
Copyright © 2011-2022 走看看