Networkx
前言
图的基本概念
-
图
概括来讲就是有一些点和中心点之间的连线组成的。定义为G=(V,E)。
V是顶戴的非空有线集合,成为顶点集;E是边的集合,成为边集。边一般用(vi,vj)表示,其中vi,vj属于顶点集V
-
无向图&有向图
-
简单图&完全图
- 简单图:无环且无重边的图称为简单图
- 完全图:任意两点均相邻的简单图称为完全图,含几个顶点的完全图记为 Kn。
-
赋权图
-
顶点的度
-
子图
-
道路与回路
-
连通图&非连通图
图的表示
本节均假设G=(V,E)为简单图
Networkx简介
networkx是一个用 Python 语言开发的图论与复杂网络建模工具,内置了常用的图与复杂网络分析算法,可以方便地进行复杂网络数据分析、仿真建模等工作.networkx 支持创建简单无向图、有向图和多重图;内置许多标准的图论算法顶点可为任意数据;支持任意的边值维度.
network创建图的相关函数
函数 | 作用 |
---|---|
Graph() | 创建无向图 |
Graph(A) | 由邻接矩阵创建无向图 |
DiGraph() | 创建有向图 |
DiGraph(A) | 由邻接矩阵创建有向图 |
MultiGraph() | 创建多重无向图 |
MultiDiGraph() | 创建多重有向图 |
add_edges() | 添加一条边 |
add_edges_from(List) | 从列表中添加一条边 |
add_node() | 添加一个顶点 |
add_nodes_from(List) | 从列表中添加一个顶点 |
dijkstra_path(G,source,target,weight=‘weight’) | 求最短路径 |
dijkstra_path_length(G,source,target,weight=‘weight’) | 求最短距离 |
创建并绘制图
实例1:
绘制无向图如下:
A = [ 0 9 2 4 7 9 0 3 4 0 2 3 0 8 4 4 4 8 0 6 7 0 4 6 0 ] A= \left[ \begin{array}{cc|r} 0\quad9\quad2\quad4\quad7\\ 9\quad0\quad3\quad4\quad0\\ 2\quad3\quad0\quad8\quad4\\ 4\quad4\quad8\quad0\quad6\\ 7\quad0\quad4\quad6\quad0 \end{array} \right] A= 0924790340230844480670460
import numpy as np
import pylab as plt
import networkx as nx
#导入数据库
a=np.zeros((5,5))
a[0,1:5]=[9,2,4,7];a[1,2:4]=[3,4]
a[2,[3,4]]=[8,4]
a[3,4]=6
print(a)
np.savetxt('Pdata.txt',a)
#生成邻接矩阵A,并保存,供以后使用
i,j=np.nonzero(a)#提取顶点的编号
w=a[i,j]#提取出A中的非零元素
edges=list(zip(i,j,w))
G=nx.Graph()#构造无向图雏形
G.add_weighted_edges_from(edges)
key=range(5);s=[str(i+1) for i in range(5)]
s=dict(zip(key,s))
#构造数据——字典,用于用索引找到节点的标号
plt.rc('font',size=18)#配置生成 的图像的大小
plt.subplot(121)
nx.draw(G,font_weight='bold',with_labels=True)
#画出图,字体为黑体,有标题
plt.subplot(122)
pos=nx.shell_layout(G)
nx.draw_networkx(G,pos,node_size=260,with_labels=True)
w=nx.get_edge_attributes(G,'weight')
nx.draw_networkx_edge_labels(G,pos,font_size=12,edge_labels=w)
plt.savefig('figure.png',dpi=500)
plt.show()
说明:
nx.Graph()
构造无向图雏形,输出的G为
Graph with 0 nodes and 0 edges
add_weight_edges_from(List)
List:二维列表,每个元素中其中包含元素起始点、终止点、权重
输出:
Graph with 5 nodes and 9 edges
nx.shell_layout(G)
作用:shell_layout() 函数会根据图的拓扑结构自动计算每个节点的坐标,并返回一个字典类型的布局结果。
{0: array([-1.00000000e+00, -8.74227766e-08]), 1: array([-0.30901712, -0.95105648]), 2: array([ 0.80901724, -0.58778495]), 3: array([0.809017 , 0.58778524]), 4: array([-0.30901742, 0.95105636])}
图形的布局由5中设置:
布局 | 说明 |
---|---|
circular_layout | 顶点在一个圆环上均匀分布 |
random_layout | 顶点随机分布 |
shell_layout | 顶点在同心圆上分布 |
spring_layout | 用Fruchterman-Reingold算法排列顶点 |
spectral_layout | 根据图的Laplace特征向量排列顶点 |
图的相关操作
import numpy as np
import pylab as plt
import networkx as nx
a=np.loadtxt('Pdata.txt')
print(a)
G=nx.Graph(a)
print('顶点集:',G.nodes(),'\n边集:',G.edges())
print('邻接表:',list(G.adjacency()))
print('列表字典:',nx.to_dict_of_lists(G))
B=nx.to_numpy_array(G)
C=nx.to_scipy_sparse_array(G)
print('B:',B)
print('C:',C)
[[0. 9. 2. 4. 7.]
[0. 0. 3. 4. 0.]
[0. 0. 0. 8. 4.]
[0. 0. 0. 0. 6.]
[0. 0. 0. 0. 0.]]
顶点集: [0, 1, 2, 3, 4]
边集: [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (2, 3), (2, 4), (3, 4)]
邻接表: [(0, {1: {'weight': 9.0}, 2: {'weight': 2.0}, 3: {'weight': 4.0}, 4: {'weight': 7.0}}), (1, {0: {'weight': 9.0}, 2: {'weight': 3.0}, 3: {'weight': 4.0}}), (2, {0: {'weight': 2.0}, 1: {'weight': 3.0}, 3: {'weight': 8.0}, 4: {'weight': 4.0}}), (3, {0: {'weight': 4.0}, 1: {'weight': 4.0}, 2: {'weight': 8.0}, 4: {'weight': 6.0}}), (4, {0: {'weight': 7.0}, 2: {'weight': 4.0}, 3: {'weight': 6.0}})]
列表字典: {0: [1, 2, 3, 4], 1: [0, 2, 3], 2: [0, 1, 3, 4], 3: [0, 1, 2, 4], 4: [0, 2, 3]}
B: [[0. 9. 2. 4. 7.]
[9. 0. 3. 4. 0.]
[2. 3. 0. 8. 4.]
[4. 4. 8. 0. 6.]
[7. 0. 4. 6. 0.]]
C: (0, 1) 9.0
(0, 2) 2.0
(0, 3) 4.0
(0, 4) 7.0
(1, 0) 9.0
(1, 2) 3.0
(1, 3) 4.0
(2, 0) 2.0
(2, 1) 3.0
(2, 3) 8.0
(2, 4) 4.0
(3, 0) 4.0
(3, 1) 4.0
(3, 2) 8.0
(3, 4) 6.0
(4, 0) 7.0
(4, 2) 4.0
(4, 3) 6.0
最短路径算法
定义10.7:设图G是赋权图,为G中的一条路.则称Г的各边权之和为路Г的长度.
对于 G 的两个顶点uo和 vo,从 uo 到 vo的路一般不止一条,其中最短的(长度最小的)一条称为从 uo 到 uo的最短路;最短路的长称为从 uo 到 uo 的距离,记为 d(uo, vo).
求最短路的算法有Diikstra(迪杰斯特拉)标号算法和 Foyd(弗洛伊德)算法等方法,但 Diijkstra 标号算法只适用于边权是非负的情形.最短路径问题也可以归结为一个 0-1 整数规划模型.
Diikstra算法
实例
求图所示的图G中从v到所有其余顶点的最短路及最短距离.
- 先写出邻接矩阵
[ 0 1 2 ∞ 7 ∞ 4 8 1 0 2 3 ∞ ∞ ∞ 7 2 2 0 1 5 ∞ ∞ ∞ ∞ 3 1 0 3 6 ∞ ∞ 7 ∞ 5 3 0 4 3 ∞ ∞ ∞ ∞ 6 4 0 6 4 4 ∞ ∞ ∞ 3 6 0 2 8 7 ∞ ∞ ∞ 4 2 0 ] \left[ \begin{array}{cc|r} 0\quad1\quad2\quad \infty \quad7\quad\infty\quad 4\quad8\\ 1\quad0\quad2\quad3\quad\infty\quad\infty\quad\infty\quad7\\ 2\quad2\quad0\quad1\quad5\quad\infty\quad\infty\quad\infty\\ \infty\quad3\quad1\quad0\quad3\quad6\quad\infty\quad\infty\\ 7\quad\infty\quad5\quad3\quad0\quad4\quad3\quad\infty\\ \infty\quad\infty\quad\infty\quad6\quad4\quad0\quad6\quad4\quad\\ 4\quad\infty\quad\infty\quad\infty\quad3\quad6\quad0\quad2\quad\\ 8\quad7\quad\infty\quad\infty\quad\infty\quad4\quad2\quad0\quad \end{array} \right] 012∞7∞481023∞∞∞722015∞∞∞∞31036∞∞7∞53043∞∞∞∞640644∞∞∞360287∞∞∞420
import numpy as np
inf=np.inf
import pylab as plt
import networkx as nx
'''Funtion:'''
def Dijkstra_all_minpath(matr,start):
#matr为邻接矩阵的数组,start表示起点
n=len(matr)#该图的节点数
dis=[];temp=[]
dis.extend(matr[start])
temp.extend(matr[start])
temp[start]=inf
visited=[start]
parent=[start]*n
while len(visited)<n:
i=temp.index(min(temp))
temp[i]=inf
for j in range(n):
if j not in visited:
if (dis[i]+matr[i][j])<dis[j]:
dis[j]=temp[j]=dis[i]+matr[i][j]
parent[j]=i
visited.append(i)
path=[]
path.append(str(i))
k=i
while parent[k]!=start:
path.append(str(parent[k]))
k=parent[k]
path.append(str(start))
path.reverse()
print(str(i)+':','->'.join(path))
return dis
a=[[0,1,2,inf,7,inf,4,8],[1,0,2,3,inf,inf,inf,7],
[2,2,0,1,5,inf,inf,inf],[inf,3,1,0,3,6,inf,inf],
[7,inf,5,3,0,4,3,inf],[inf,inf,inf,6,4,0,6,4],
[4,inf,inf,inf,3,6,0,2],[8,7,inf,inf,inf,4,2,0]]
d=Dijkstra_all_minpath(a,3)
print('v3到所有顶点的最短距离:',d)
2: 3->2
0: 3->2->0
1: 3->1
4: 3->4
5: 3->5
6: 3->4->6
7: 3->4->6->7
v3到所有顶点的最短距离: [3, 3, 1, 0, 3, 6, 6, 8]
方法2:networkx
import numpy as np
inf=np.inf
import pylab as plt
import networkx as nx
List=[(0,1,1),(0,2,2),(0,4,7),(0,6,4),(0,7,8),(1,2,2),(1,3,3),
(1,7,7),(2,3,1,),(2,4,5),(3,4,3),(3,5,6),(4,5,4),(4,6,3),(5,6,6),(5,7,4),(6,7,2)]
G=nx.Graph()
G.add_weighted_edges_from(List)
A=nx.to_numpy_array(G,nodelist=range(8))
np.savetxt('Pdata10_6.txt',A)
p=nx.dijkstra_path(G,source=3,target=7,weight='weight')
d=nx.dijkstra_path_length(G,3,7,weight='weight')
print('最短路径:',p,'\n最短距离:',d)
最短路径: [3, 4, 6, 7]
最短距离: 8
Foyd算法
用于求每对顶点间的最短路径算法
方法是:每次以不同的顶点作为起点,用 Dijkstra 算法求出从该起点到其余顶点的最短路,反复执行 n-1(n 为顶点个数)次这样的操作,就可得到每对顶点之间的最短路.但这样做需要大量的重复计算,效率不高.为此,R.W.Floyd 另辟蹊径于1962年提出了一个直接寻求任意两顶点之间最短路的算法.
赋权图:G=(V,E,A0),其中
顶点集
V
=
{
v
1
,
.
.
.
,
v
n
}
A
=
[
a
11
a
12
.
.
.
a
1
n
a
21
a
21
.
.
.
a
2
n
.
.
.
.
.
.
.
.
.
.
.
.
a
n
1
a
n
2
.
.
.
a
n
n
]
这里
a
i
j
=
{
v
i
与
v
j
之间边的权值,
v
i
与
v
i
之间有边
∞
,
v
i
与
v
j
之间无边
a
i
i
=
0
,
i
=
1
,
2
,
.
.
.
,
n
对于无向图,
A
0
是堆成矩阵,
a
i
j
=
a
j
i
=
1
,
2
,
.
.
.
,
n
顶点集V=\{v_1,...,v_n\}\\ A= \left[ \begin{matrix} a_{11}\quad a_{12}\quad...\quad a_{1n}\\ a_{21}\quad a_{21}\quad...\quad a_{2n}\\ ...\quad...\quad...\quad...\quad\\ a_{n1}\quad a_{n2}\quad ...\quad a_{nn} \end{matrix} \right]\\这里a_{ij}= \begin{cases} v_i与v_j之间边的权值,\thinspace v_i与v_i之间有边\\ \infty,\quad v_i与v_j之间无边 \end{cases}\\ a_{ii}=0,\quad i=1,2,...,n\\ 对于无向图,A_0是堆成矩阵,a_ij=a_ji=1,2,...,n
顶点集V={v1,...,vn}A=
a11a12...a1na21a21...a2n............an1an2...ann
这里aij={vi与vj之间边的权值,vi与vi之间有边∞,vi与vj之间无边aii=0,i=1,2,...,n对于无向图,A0是堆成矩阵,aij=aji=1,2,...,n
import numpy as np
inf=np.inf
import pylab as plt
import networkx as nx
def floyd(graph):
m=len(graph)
dis=graph #get distance
path=np.zeros((m,m))
for k in range(m):
for i in range(m):
for j in range(m):
if dis[i][k] + dis[k][j] < dis[i][j]:
dis[i][j]=dis[i][k]+dis[k][j]
path[i][j]=k
dis=np.matrix(dis)
return dis,path
inf=np.inf
a=[[0,1,2,inf,7,inf,4,8],[1,0,2,3,inf,inf,inf,7],
[2,2,0,1,5,inf,inf,inf],[inf,3,1,0,3,6,inf,inf],
[7,inf,5,3,0,4,3,inf],[inf,inf,inf,6,4,0,6,4],
[4,inf,inf,inf,3,6,0,2],[8,7,inf,inf,inf,4,2,0]]
dis,path=floyd(a)
print('所有顶点对之间的最短距离为:\n',dis,'\n','路由矩阵为:\n',path)
所有顶点对之间的最短距离为:
[[0 1 2 3 6 9 4 6]
[1 0 2 3 6 9 5 7]
[2 2 0 1 4 7 6 8]
[3 3 1 0 3 6 6 8]
[6 6 4 3 0 4 3 5]
[9 9 7 6 4 0 6 4]
[4 5 6 6 3 6 0 2]
[6 7 8 8 5 4 2 0]]
路由矩阵为:
[[0. 0. 0. 2. 3. 3. 0. 6.]
[0. 0. 0. 0. 3. 3. 0. 0.]
[0. 0. 0. 0. 3. 3. 0. 6.]
[2. 0. 0. 0. 0. 0. 4. 6.]
[3. 3. 3. 0. 0. 0. 0. 6.]
[3. 3. 3. 0. 0. 0. 0. 0.]
[0. 0. 0. 4. 0. 0. 0. 0.]
[6. 0. 6. 6. 6. 0. 0. 0.]]
直接调用
import numpy as np
inf=np.inf
import pylab as plt
import networkx as nx
a=np.loadtxt('Pdata10_6.txt')
G=nx.Graph(a)
d=nx.shortest_path_length(G,weight='weight')
Ld=dict(d)
print('顶点对之间的最短距离为:',Ld)
print('顶点0到顶点4的最短距离为:',Ld[0][4])
m,n=a.shape;dd=np.zeros((m,n))
for i in range(m):
for j in range(n):
dd[i,j]=Ld[i][j]
print('顶点对之间最短距离的数组表示为:\n',dd)
np.savetxt('Pdata10_8.txt',dd)
p=nx.shortest_path(G,weight='weight')
dp=dict(p)
print('\n顶点对之间的最短距离为:',dp)
print('顶点0到顶点4的最短路径为:',dp[0][4])
顶点对之间的最短距离为: {0: {0: 0, 1: 1.0, 2: 2.0, 3: 3.0, 6: 4.0, 4: 6.0, 7: 6.0, 5: 9.0}, 1: {1: 0, 0: 1.0, 2: 2.0, 3: 3.0, 6: 5.0, 4: 6.0, 7: 7.0, 5: 9.0}, 2: {2: 0, 3: 1.0, 0: 2.0, 1: 2.0, 4: 4.0, 6: 6.0, 5: 7.0, 7: 8.0}, 3: {3: 0, 2: 1.0, 1: 3.0, 4: 3.0, 0: 3.0, 5: 6.0, 6: 6.0, 7: 8.0}, 4: {4: 0, 3: 3.0, 6: 3.0, 5: 4.0, 2: 4.0, 7: 5.0, 1: 6.0, 0: 6.0}, 5: {5: 0, 4: 4.0, 7: 4.0, 3: 6.0, 6: 6.0, 2: 7.0, 1: 9.0, 0: 9.0}, 6: {6: 0, 7: 2.0, 4: 3.0, 0: 4.0, 1: 5.0, 5: 6.0, 3: 6.0, 2: 6.0}, 7: {7: 0, 6: 2.0, 5: 4.0, 4: 5.0, 0: 6.0, 1: 7.0, 3: 8.0, 2: 8.0}}
顶点0到顶点4的最短距离为: 6.0
顶点对之间最短距离的数组表示为:
[[0. 1. 2. 3. 6. 9. 4. 6.]
[1. 0. 2. 3. 6. 9. 5. 7.]
[2. 2. 0. 1. 4. 7. 6. 8.]
[3. 3. 1. 0. 3. 6. 6. 8.]
[6. 6. 4. 3. 0. 4. 3. 5.]
[9. 9. 7. 6. 4. 0. 6. 4.]
[4. 5. 6. 6. 3. 6. 0. 2.]
[6. 7. 8. 8. 5. 4. 2. 0.]]
顶点对之间的最短距离为: {0: {0: [0], 1: [0, 1], 2: [0, 2], 4: [0, 2, 3, 4], 6: [0, 6], 7: [0, 6, 7], 3: [0, 2, 3], 5: [0, 2, 3, 5]}, 1: {1: [1], 0: [1, 0], 2: [1, 2], 3: [1, 3], 7: [1, 7], 4: [1, 3, 4], 6: [1, 0, 6], 5: [1, 3, 5]}, 2: {2: [2], 0: [2, 0], 1: [2, 1], 3: [2, 3], 4: [2, 3, 4], 5: [2, 3, 5], 6: [2, 0, 6], 7: [2, 0, 6, 7]}, 3: {3: [3], 1: [3, 1], 2: [3, 2], 4: [3, 4], 5: [3, 5], 0: [3, 2, 0], 7: [3, 4, 6, 7], 6: [3, 4, 6]}, 4: {4: [4], 0: [4, 3, 2, 0], 2: [4, 3, 2], 3: [4, 3], 5: [4, 5], 6: [4, 6], 1: [4, 3, 1], 7: [4, 6, 7]}, 5: {5: [5], 3: [5, 3], 4: [5, 4], 6: [5, 6], 7: [5, 7], 0: [5, 3, 2, 0], 2: [5, 3, 2], 1: [5, 3, 1]}, 6: {6: [6], 0: [6, 0], 4: [6, 4], 5: [6, 5], 7: [6, 7], 1: [6, 0, 1], 2: [6, 0, 2], 3: [6, 4, 3]}, 7: {7: [7], 0: [7, 6, 0], 1: [7, 1], 5: [7, 5], 6: [7, 6], 4: [7, 6, 4], 3: [7, 6, 4, 3], 2: [7, 6, 0, 2]}}
顶点0到顶点4的最短路径为: [0, 2, 3, 4]
最小生成树
树(tree)是图论中非常重要的一类图,它非常类似于自然界中的树,结构简单、应用广泛,最小生成树问题则是其中的经典问题之一.在实际应用中,许多问题的图论模型都是最小生成树,如通信网络建设、有线电缆铺设、加工设备分组等。
基本概念
定义1:连通的无圈图称为数
定义2:设G是具有几个顶点m条边的图,则以下命题等价。
(1)图G 是树;
(2)图G 中任意两个不同顶点之间存在唯一的路;
(3)图G连通,删除任一条边均不连通:
(4)图G连通,且n=m+1;
(5)图G无圈,添加任一条边可得唯一的圈;
(6)图G无圈,且n=m+1.
定义3:若图G的生成子图是树,则称为G的生成树或支撑树
一个图的生成树通常不唯一!
定理1:连通图的生成树一定存在
证明给定连通图G,若G无圈,则G本身就是自己的生成树.若G有圈则任取 G 中一个圈 C,记删除 中一条边后所得之图为 G’.显然 G’中圈C 已经不存在,但 G’仍然连通,若’中还有圈,再重复以上过程,直至得到一个无圈的连通图H.易知是G的生成树。
此证明方法也是求生成树的一种方法,称为“破圈法”
定义4:在赋权图G中,边权之和最小的生成树称为 G的最小生成树,一个简单连通图只要不是树,其生成树一般不唯一,而且非常多。一般地,n个顶点的完全图,其不同生成树的个数为 (n^n)-2。因而,寻求一个给定赋权图的最小生成树,一般是不能用枚举法的.例如,20个顶点的完全图有2018个生成树,2018 有24 位.所以,通过枚举求最小生成树是无效的算法,必须寻求有效的算法。
求最小生成树
对于赋权连通图G=(V,E,W),其中V为顶点集合,E为边的集合,W为邻接矩阵,这里顶点集合V中有n个顶点构造它的最小生成树.构造连通图最小生成树的算法有Kruskal算法和 Prim 算法
Kruskal算法
Kruskal算法思想:每次将一条权最小的边加入子图T中,并保证不形成圈
Kruskal算法如下:
(1)选e1∈E,使得e1是权值最小的边
(2)若e1,e2,…,ei已选好,则从E-{e1,e2,…,ei}中选取 e_{i+1},使得
(i){e1,e2,……,ei,ei+1}中无圈,
(ii)e _{i+1}是E-{e1,e2,……,e;}中权值最小的边
(3)直到选得en-1为止.
示例
用Kruskal 算法求如图 所示连通图的最小生成树
解:
1.构造最小生成树的连通图解首先将给定图 G的边按照权值从小到大进行排序,如图:
2.其次,依照 Kruskal 算法的步骤,迭代4步完成最小生成树的构造.按照边的排列顺序,前三次取定
e
1
=
(
v
3
,
v
5
)
,
e
2
=
(
v
1
,
v
5
)
,
e
3
=
(
v
3
,
v
4
)
.
e1=(v_3,v_5),e2=(v_1,v_5),e3 =(v_3, v_4).
e1=(v3,v5),e2=(v1,v5),e3=(v3,v4).
由于下一个未选边中的最小权边(v1,v3)与已选边 e1,e2构成圈,所以排除.第4次选 e4=(u2,u),得到图 10.12所示的树就是图G的一棵最小生成树,它的权值是 9.
Prim算法
设置两个集合P和Q,其中尸用于存放G的最小生成树中的顶点,集合Q存放G的最小生成树中的边.令集合P的初值为P={v1}(假设构造最小生成树时,从顶点 v1出发),集合 Q 的初值为 Q=8(空集).
Prim算法思想
从所有p ∈P,v∈ V-P的边中,选取具有最小权值的边pv,将顶点v加入集合P中,将边 pv 加入集合 Q 中,如此不断重复,直到 P=V时,最小生成树构造完毕,这时集合 Q中包含了最小生成树的所有边.
Prim 算法如下:
(1)P={u1},Q=空集;
(2)while P~=V
找最小边 pv,其中p∈P,v∈V-P;
P=P+ {v};
Q=Q+ {pv};
end
示例
用Prim算法求如图 所示连通图的最小生成树
解:按照 Prim 算法的步骤,迭代4步完成最小生成树的构造:
(0)第0步初始化,顶点集 P={v1},边集 Q=空集;
(1)第1步,找到最小边(v1,v5),P={v1,v5},Q={(v1,v5)};
(2)第2步,找到最小边(v3,v5),P={v1,v3,v5},Q={(v1,v5),(v3,v5)};
(3)第3步,找到最小边(u3,v4),P={v1,v3,v4,v5},Q ={(v1,v5),(v3,v5),(v3,v4)};
(4)第4步,找到最小边(v2,v3),P={v1,v2,v3,v4,v5},Q={(v1,v5),(v3,v5),(v3,v4),(v2,v3)}最小生成树构造完毕
用Networkx求最小生成树
函数:minimum_spanning_tree
格式:
T=minimum_spanning_tree(G,weight='weight',algorithm='kruskal')
其中,G为输入的图,algorithm的取值有三种字符串:‘kruskal’ , ‘prim’ 或 ‘boruvka’(缺省时默认为‘kruskal’ )
返回值T为所求的的最小生成树的可迭代对象
import numpy as np
inf=np.inf
import pylab as plt
import networkx as nx
L=[(1,2,8),(1,3,4),(1,5,2),(2,3,4),(3,4,2),(3,5,1),(4,5,5)]
#假设一个赋权图
b=nx.Graph()
b.add_nodes_from(range(1,6))
b.add_weighted_edges_from(L)
T=nx.minimum_spanning_tree(b)
#对b求最小生成树,并存到T
w=nx.get_edge_attributes(T,'weight')
TL=sum(w.values())
print('最小生成树为:',w)
print('最小生成树的长度为:',TL)
pos=nx.shell_layout(b)
nx.draw(T,pos,node_size=280,with_labels=True,node_color='r')
nx.draw_networkx_edge_labels(T,pos,edge_labels=w)
plt.show()
T=nx.minimum_spanning_tree()
作用:对b求最小生成树,并存到T