1、生成树和最小生成树

1.1 生成树

连通的无圈图称为树,就是不包含循环的回路的连通图。

对于无向连通图,生成树(Spanning tree)是原图的极小连通子图,它包含原图中的所有 n 个顶点,并且有保持图连通的最少的边,即只有足以构成一棵树的 n-1 条边。

生成树满足:

  • (1)包含连通图中所有的顶点;
  • (2)任意两顶点之间有且仅有一条通路。

因此,生成树中边的数量 = 顶点数 - 1。

对于非连通无向图, 遍历每个连通分量中的顶点集合所经过的边是多颗生成树,这些连通分量的生成树构成非连通图的生成森林 。

欢迎关注 Youcans 原创系列,数模笔记每周更新

Python数模笔记-PuLP库
Python数模笔记-StatsModels统计回归
Python数模笔记-Sklearn
Python数模笔记-NetworkX
Python数模笔记-模拟退火算法

1.2 最小生成树和最大生成树

遍历连通图的方式有多种,也就是说对于一张连通图,可能有多种不同的生成树。

带权的连通图的生成树中各条边的权重之和最小的生成树,称为最小生成树(minimum spanning tree,MST),也称最小权重生成树。

对应地,各条边的权重之和最大的生成树,称为最大生成树。

生成树和最小生成树有许多重要的应用。例如在若干城市之间铺设通信线路,使任意两个城市之间都可以通信,要使铺设线路的总费用最低,就需要找到最小生成树。


2、最小生成树算法

构造最小生成树的算法很多,通常是基于MST性质,从空树开始,按照贪心法逐步选择并加入 n-1 条安全边(不产生回路),最终生成一棵最小生成树。

最小生成树的典型算法有普里姆算法(Prim算法)和克鲁斯卡算法(Kruskal算法)。

2.1 普里姆算法(Prim算法)

Prim 算法以顶点为基础构造最小生成树:从某一个顶点 s 开始,每次选择剩余的代价最小的边所对应的顶点,加入到最小生成树的顶点集合中,逐步扩充直到包含整个连通网的所有顶点,可以称为“加点法”。Prim算法中每个顶点只与连通图连接一次,因此不用考虑在加入顶点的过程中是否会形成回路。

Prim 算法中图的存贮结构采用邻接矩阵,使用一个顶点集合 u 构造最小生成树。由于不断向集合u中加点,还需要建立一个辅助数组来同步更新最小代价边的信息。

Prim 算法每次选择顶点时,都需要进行排序,但每次都只需要对一部分边进行排序。Prim 算法的时间复杂度为 O(n*n),与边的数量无关,适用于边很多的稠密图。采用堆实现优先队列来维护最小点,可以将Prim算法的时间复杂度降低到 O(mlogn),称为Prim_heap 算法,但该算法的空间消耗很大。

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

Kruskal 算法以边为基础构造最小生成树:初始边数为 0,每次选择一条满足条件的最小代价边,加入到边集合中,逐步扩充直到包含整个生成树,可以称为“加边法”。Kruskal 算法是利用避圈思想,每次找到不使图构成回路的代价最小的边。

Kruskal 算法中图的存贮结构采用边集数组,权值相等的边在数组中的排列次序是任意的。

Kruskal算法开始就要对所有的边进行排序,之后还需要对所有边应用 Union-Find算法,但不再需要排序。Kruskal 算法的时间复杂度为 O(mlogm),主要是对边排序的时间复杂度,适用于边较少的稀疏图。


3、NetworkX 的最小生成树算法

3.1 最小/最大生成树函数

函数 功能
minimum_spanning_tree(G[, weight,…]) 计算无向图上的最小生成树
maximum_spanning_tree(G[, weight,…]) 计算无向图上的最大生成树
minimum_spanning_edges(G[, algorithm,…]) 计算无向加权图最小生成树的边
maximum_spanning_edges(G[, algorithm,…]) 计算无向加权图最大生成树的边

3.2 minimum_spanning_tree() 使用说明

minimum_spanning_tree(G, weight=‘weight’, algorithm=‘kruskal’, ignore_nan=False)

minimum_spanning_edges(G, algorithm=‘kruskal’, weight=‘weight’, keys=True, data=True, ignore_nan=False)

minimum_spanning_tree() 用于计算无向连通图的最小生成树(森林)。minimum_spanning_edges() 用于计算无向连通图的最小生成树(森林)的边。
对于连通无向图,计算最小生成树;对于非连通无向图,计算最小生成森林。

主要参数:

  • G(undirected graph):无向图。
  • weight(str):指定用作计算权重的边属性。
  • algorithm(string):计算最小生成树的算法,可选项为 ‘kruskal’、‘prim’ 或 ‘boruvka’。默认算法为 ‘kruskal’。
  • data(bool):指定返回值是否包括边的权值。
  • ignore_nan(bool) :在边的权重为 Nan 时产生异常。

返回值:

  • minimum_spanning_tree() 的返回值是最小生成树,类型为<class ‘networkx.classes.graph.Graph’> 。
  • minimum_spanning_edges() 的返回值是最小生成树的构成边,类型为<class ‘generator’>。

3.3 minimum_spanning_tree() 算法使用例程

本案例问题来自:司守奎、孙兆亮,数学建模算法与应用(第2版),P48,例4.5,国防工业出版社。

例:最小生成树问题。已知如图的有权无向图,求最小生成树。

# networkX_E4.py
# Demo of minimum spanning tree(MST) with NetworkX
# Copyright 2021 YouCans, XUPT
# Crated:2021-05-21import matplotlib.pyplot as plt # 导入 Matplotlib 工具包
import networkx as nx  # 导入 NetworkX 工具包G = nx.Graph()  # 创建:空的 无向图
G.add_weighted_edges_from([(1,2,50),(1,3,60),(2,4,65),(2,5,40),(3,4,52),(3,7,45),(4,5,50),(4,6,30),(4,7,42),(5,6,70)])  # 向图中添加多条赋权边: (node1,node2,weight)T = nx.minimum_spanning_tree(G)  # 返回包括最小生成树的图
print(T.nodes)  # [1, 2, 3, 4, 5, 7, 6]
print(T.edges)  # [(1,2), (2,5), (3,7), (4,6), (4,7), (4,5)]
print(sorted(T.edges)) # [(1,2), (2,5), (3,7), (4,5), (4,6), (4,7)]
print(sorted(T.edges(data=True)))  # data=True 表示返回值包括边的权重
# [(1,2,{'weight':50}), (2,5,{'weight':40}), (3,7,{'weight':45}), (4,5,{'weight':50}), (4,6,{'weight':30}), (4,7,{'weight':42})]mst1 = nx.tree.minimum_spanning_edges(G, algorithm="kruskal") # 返回值 带权的边
print(list(mst1))
# [(4,6,{'weight':30}), (2,5,{'weight':40}), (4,7,{'weight':42}), (3,7,{'weight':45}), (1,2,{'weight':50}), (4,5,{'weight':50})]
mst2 = nx.tree.minimum_spanning_edges(G, algorithm="prim",data=False)  # data=False 表示返回值不带权
print(list(mst2))
# [(1,2), (2,5), (5,4), (4,6), (4,7), (7,3)]pos={1:(2.5,10),2:(0,5),3:(7.5,10),4:(5,5),5:(2.5,0),6:(7.5,0),7:(10,5)}  # 指定顶点位置
nx.draw(G, pos, with_labels=True, alpha=0.8)  # 绘制无向图
labels = nx.get_edge_attributes(G,'weight')  # YouCans, XUPT
nx.draw_networkx_edge_labels(G,pos,edge_labels=labels, font_color='c') # 显示边的权值
nx.draw_networkx_edges(G,pos,edgelist=T.edges,edge_color='r',width=4)  # 设置指定边的颜色
plt.show()

3.4 程序运行结果

[1, 2, 3, 4, 5, 7, 6]
[(1, 2), (2, 5), (3, 7), (4, 6), (4, 7), (4, 5)]
[(1, 2), (2, 5), (3, 7), (4, 5), (4, 6), (4, 7)]
[(1, 2, {'weight': 50}), (2, 5, {'weight': 40}), (3, 7, {'weight': 45}), (4, 5, {'weight': 50}), (4, 6, {'weight': 30}), (4, 7, {'weight': 42})]
[(4, 6, {'weight': 30}), (2, 5, {'weight': 40}), (4, 7, {'weight': 42}), (3, 7, {'weight': 45}), (1, 2, {'weight': 50}), (4, 5, {'weight': 50})]
[(1, 2), (2, 5), (5, 4), (4, 6), (4, 7), (7, 3)]

3.5 程序说明

  1. 图的输入。本例为稀疏的有权无向图,使用 G.add_weighted_edges_from() 函数可以使用列表向图中添加多条赋权边,每个赋权边以元组 (node1,node2,weight) 表示。
  2. nx.minimum_spanning_tree() 和 nx.tree.minimum_spanning_edges() 都可以计算最小生成树,参数设置和属性也基本一致。区别主要在于返回值:nx.minimum_spanning_tree() 返回值是最小生成树构成的图(‘Graph’),需要用 T.edges() 调用对应的最小生成树的边。nx.tree.minimum_spanning_edges() 返回值是最小生成树的构成边(‘generator’),需要用 list() 转换为列表数据。

版权说明:
YouCans 原创作品:Python 数模笔记

本文内容及例程为作者原创,并非转载书籍或网络内容。
本文中案例问题来自:司守奎、孙兆亮,数学建模算法与应用(第2版),国防工业出版社

YouCans 原创作品,转载需标注原始链接。
Copyright 2021 YouCans, XUPT
Crated:2021-05-21

欢迎关注 Youcans 原创系列,每周更新数模笔记

Python数模笔记-PuLP库(1)线性规划入门
Python数模笔记-PuLP库(2)线性规划进阶
Python数模笔记-PuLP库(3)线性规划实例
Python数模笔记-Scipy库(1)线性规划问题
Python数模笔记-StatsModels 统计回归(1)简介
Python数模笔记-StatsModels 统计回归(2)线性回归
Python数模笔记-StatsModels 统计回归(3)模型数据的准备
Python数模笔记-StatsModels 统计回归(4)可视化
Python数模笔记-Sklearn (1)介绍
Python数模笔记-Sklearn (2)聚类分析
Python数模笔记-Sklearn (3)主成分分析
Python数模笔记-Sklearn (4)线性回归
Python数模笔记-Sklearn (5)支持向量机
Python数模笔记-模拟退火算法(1)多变量函数优化
Python数模笔记-模拟退火算法(2)约束条件的处理
Python数模笔记-模拟退火算法(3)整数规划问题
Python数模笔记-模拟退火算法(4)旅行商问题
Python数模笔记-NetworkX(1)图的操作
Python数模笔记-NetworkX(2)最短路径
Python数模笔记-NetworkX(3)条件最短路径

Python数模笔记-NetworkX(4)最小生成树相关推荐

  1. Python数模笔记-NetworkX(3)条件最短路径

    1.带有条件约束的最短路径问题 最短路径问题是图论中求两个顶点之间的最短路径问题,通常是求最短加权路径. 条件最短路径,指带有约束条件.限制条件的最短路径.例如,顶点约束,包括必经点或禁止点的限制:边 ...

  2. Python数模笔记-NetworkX(2)最短路径

    1.最短路径问题的常用算法 最短路径问题是图论研究中的经典算法问题,用于计算图中一个顶点到另一个顶点的最短路径. 欢迎关注 Youcans 原创系列,每周更新数模笔记 Python数模笔记-PuLP库 ...

  3. Python数模笔记-NetworkX(1)图的操作

    1.NetworkX 图论与网络工具包 NetworkX 是基于 Python 语言的图论与复杂网络工具包,用于创建.操作和研究复杂网络的结构.动力学和功能. NetworkX 可以以标准和非标准的数 ...

  4. Python数模笔记-Sklearn(4)线性回归

    1.什么是线性回归? 回归分析(Regression analysis)是一种统计分析方法,研究自变量和因变量之间的定量关系.回归分析不仅包括建立数学模型并估计模型参数,检验数学模型的可信度,也包括利 ...

  5. Python数模笔记-Sklearn(2)聚类分析

    1.分类的分类 分类的分类?没错,分类也有不同的种类,而且在数学建模.机器学习领域常常被混淆. 首先我们谈谈有监督学习(Supervised learning)和无监督学习(Unsupervised ...

  6. Python数模笔记-Sklearn (1)介绍

    1.SKlearn 是什么 Sklearn(全称 SciKit-Learn),是基于 Python 语言的机器学习工具包. Sklearn 主要用Python编写,建立在 Numpy.Scipy.Pa ...

  7. Python数模笔记-StatsModels 统计回归(3)模型数据的准备

    1.读取数据文件 回归分析问题所用的数据都是保存在数据文件中的,首先就要从数据文件读取数据. 数据文件的格式很多,最常用的是 .csv,.xls 和 .txt 文件,以及 sql 数据库文件的读取 . ...

  8. Python数模笔记-StatsModels 统计回归(2)线性回归

    1.背景知识 1.1 插值.拟合.回归和预测 插值.拟合.回归和预测,都是数学建模中经常提到的概念,而且经常会被混为一谈. 插值,是在离散数据的基础上补插连续函数,使得这条连续曲线通过全部给定的离散数 ...

  9. Python数模笔记-StatsModels 统计回归(1)简介

    1.关于 StatsModels statsmodels(http://www.statsmodels.org)是一个Python库,用于拟合多种统计模型,执行统计测试以及数据探索和可视化. 欢迎关注 ...

最新文章

  1. php range第二个参数比第一个小,鲜为人知的 PHP range() 函数
  2. CSS 从入门到放弃系列:CSS的引入方式
  3. ural 1014. Product of Digits
  4. 【撸码师的备忘录】java对redis的基本操作
  5. [css] 一个页面引用多个文件,如何防止样式冲突?
  6. 一些社会运行的底层规律,和你的利益息息相关
  7. 百度地图获取河流_想要提高学生对地理的兴趣,就要多利用地图,培养学生的思维能力...
  8. otn系统中常用的电层_WDM与OTN浅谈
  9. http协议介绍及httpd特性详解
  10. file处理的一些内容
  11. 微服务框架自带uuid生成器
  12. 车型代号对照表_2017年最新主机厂OEM车型代号对照表
  13. 第五人格显示服务器维护中请稍后登录怎么办,第五人格维护登不上怎么办 服务器维护中详情...
  14. SpringBoot整合腾讯云COS
  15. 计算机系统指定文件类型,Win7系统下设置显示已知文件类型的扩展名
  16. 无法在此iPhone激活面容ID怎么办?
  17. exchange rate维护
  18. 使用行列式公式求多边形面积
  19. 从外包公司到今日头条offer,吐血整理
  20. 3DLC系列:A/B 网格应用实践

热门文章

  1. 实现springboot的starter
  2. keyProperty=“id“ 和useGeneratedKeys=“true“作用
  3. Java预科篇2-环境搭建
  4. springsession分布式登录被覆盖_拉勾 分布式 学习小结
  5. python怎么发送邮件_Python面试题之如何用Python来发送邮件?
  6. 不超过20位的小数正则_意甲身价最贵的20位球星,国米多达7人超过尤文,夺冠成硬任务...
  7. android纹理存储,Android:OpenGL存储纹理多长时间?
  8. MySQL 高级 —— 索引实现的思考
  9. LeetCode算法入门- Longest Palindromic Substring-day5
  10. 兰州交通大学计算机科学与技术排名,兰州交通大学怎么样 全国排名是多少