博客
关于我
最小生成树——Kruskal
阅读量:379 次
发布时间:2019-03-05

本文共 1933 字,大约阅读时间需要 6 分钟。

给定一个n个点m条边的无向图,图中可能存在重边和自环,边权可能为负数。求最小生成树的树边权重之和,如果最小生成树不存在则输出impossible。以下是详细的步骤说明和代码实现。

算法思想

Kruskal算法是一种广泛用于求解最小生成树的高效方法,尤其适用于稀疏图。其核心思想可以总结为以下几个步骤:

  • 排序边:将所有边按权重从小到大进行排序。这一步的时间复杂度为O(m log m),因为需要对m条边进行排序。

  • 并查集初始化:使用并查集数据结构来跟踪每个顶点所属的连通分量。并查集的路径压缩和按秩合并操作能够保证操作的高效性,时间复杂度分别为O(α(m))和O(m),其中α是阿克曼函数的反函数,非常接近常数。

  • 遍历边并选择边:按权重从小到大遍历每一条边,检查其两个端点是否在同一个连通分量中:

    • 如果在同一个连通分量中,跳过这条边。
    • 如果不在同一个连通分量中,合并这两个顶点的连通分量,并将这条边加入生成树,增加总权重。
  • 判断生成树是否存在:在遍历完所有边后,检查生成树中包含的顶点数是否等于n。如果等于,说明存在最小生成树,输出总权重;如果不等于,说明图中存在环,无法形成生成树,输出impossible。

  • 时间复杂度

    Kruskal算法的时间复杂度主要由两部分决定:

    • 边排序:O(m log m)
    • 边遍历及并查集操作:O(m α(m)),由于α(m)非常接近于常数,时间复杂度实际上接近O(m)。

    因此,Kruskal算法的总时间复杂度为O(m log m),适用于处理较大的稀疏图。

    代码实现

    以下是使用C++语言实现的Kruskal算法的代码:

    #include 
    using namespace std;const int N = 100, M = 200;int p[N];int n, m;struct edge { int a, b, w; bool operator<(const edge &e) const { return w < e.w; }};int find(int x) { if (p[x] != x) { p[x] = find(p[x]); } return p[x];}int kruskal() { int res = 0, cnt = 1; sort(e + 1, e + m + 1); for (int i = 1; i <= m; ++i) { int a = e[i].a, b = e[i].b, w = e[i].w; a = find(a), b = find(b); if (a != b) { p[a] = b; res += w; cnt++; } } return cnt == n ? res : -1;}int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) { p[i] = i; } for (int i = 1; i <= m; ++i) { int a, b, w; scanf("%d%d%d", &a, &b, &w); e[i] = {a, b, w}; } int t = kruskal(); if (t == -1) { puts("impossible"); } else { printf("%d\n", t); } return 0;}

    代码解释

  • 数据结构定义

    • struct edge定义了边的结构,包含两个顶点和权重,并支持按权重排序。
    • int p[N];用于并查集操作,记录每个顶点的父节点。
  • 并查集函数

    • int find(int x);实现路径压缩,找到x的根节点。
  • Kruskal主函数

    • 初始化生成树的总权重和顶点数。
    • 排序边。
    • 遍历每条边,检查其两个端点是否连通,若不连通则合并并加入生成树。
    • 检查生成树是否包含所有顶点,返回结果。
  • 输入处理

    • 读取顶点数和边数。
    • 初始化并查集。
    • 读取并存储所有边。
  • 输出结果

    • 根据Kruskal函数的返回值输出impossible或最小生成树的总权重。
  • 总结

    通过以上方法,可以有效地求解给定图的最小生成树问题。Kruskal算法的高效性和代码的简洁性使其成为处理此类问题的理想选择。

    转载地址:http://ujlwz.baihongyu.com/

    你可能感兴趣的文章
    VTK:Medical之MedicalDemo2
    查看>>
    c语言(基本数据类型)实参与形参传值 用汇编理解
    查看>>
    基于单片机可控音乐流水灯控制设计-全套资料
    查看>>
    基于单片机简易信号误差分析设计-全套资料
    查看>>
    基于单片机简易脉搏测量仪系统设计-毕设课设资料
    查看>>
    并发框架下的“基础类型”——浅析基本类型、ThreadLocal、原子类的线程安全机制
    查看>>
    VHDL代码风格
    查看>>
    图像处理系列1.skimage
    查看>>
    Object Clone
    查看>>
    Javascript中String支持使用正则表达式的四种方法
    查看>>
    2021年判断浏览器最新写法,你都掌握了吗?
    查看>>
    【IoT】蓝牙BLE基础:CC254x通信系列之模拟SPI协议
    查看>>
    【IoT】TI BLE CC2541 串口控制蓝牙详解
    查看>>
    【产品】项目管理的五个过程和九大知识领域之二
    查看>>
    【项目管理】项目管理流程浅析
    查看>>
    【Tool】如何使用 Uniflash 烧写 WIFI 芯片 CC3200
    查看>>
    copy_{to, from}_user()的思考
    查看>>
    Web前端安全策略之CSRF的攻击与防御
    查看>>
    纯客户端页面关键字搜索高亮jQuery插件
    查看>>
    linux运维中常用的命令
    查看>>