Python:利用邻接矩阵判断有向图的连通性

2021年9月16日 9点热度 0条评论 来源: 呆猫_NerdyCat

Python求解:利用邻接矩阵判断有向图的连通性

 WoW,让我们先来看看我们要解决的小问题:

            —— 将任意一个有向图G采用矩阵输入,图形化输出图G,利用可达矩阵判定图G是否连通:

 

        (PS:判断图的连通性至少可以有[1].并查集  [2].DFS  [3].BFS 三种方法,关于其他求解方法,详见:https://blog.csdn.net/weixin_44646116/article/details/95523884

           当然,今天我们主要从数学角度探讨如何利用邻接矩阵来判断图的连通性:

    首先,我们需要一点数理知识:

          (一)邻接矩阵(Adjacency Matrix)是表示顶点之间相邻关系的矩阵。设G=(V,E)是一个图,其中V={v1,v2,…,vn} 

                       V和E集合,其中,V是顶点,E是边。因此,用一个一维数组存放图中所有顶点数据;

                       一个二维数组存放顶点间关系(边或弧)的数据,这个二维数组称为邻接矩阵。邻接矩阵又分为有向图邻接矩阵和无向图邻接矩阵;

                      在图的邻接矩阵表示法中:

                     ① 用邻接矩阵表示顶点间的相邻关系

                     ② 用一个顺序表来存储顶点信息

      给出一个 具体的邻接矩阵(无边权值):

    再拿出书上的具体例子给你们理解一下下:

 

 

  (二)可达矩阵(reachability matrix)指的是用矩阵形式来描述有向图的各节点之间经过一定长度的通路后可达到的程度。可达矩阵的计算方法是利用布尔矩阵的运算性质。

              里面的布尔矩阵,指的是方阵,矩阵中的第i行与第i列对应同一个要素。

     这一段书中描写的比较详细,涉及求解可达矩阵的数学原理,以及图的连通性的判别方法,还请仔细阅读:

代码实现部分:

#编程实现有向图连通性的判断
import numpy as np#引入numpy模块,需提前安装
import networkx as nx#引入numpy模块,需提前安装,用于绘制有向图
import matplotlib.pyplot as plt#引入matplotlib模块,同样用于绘制有向图
import pylab
#---------------------------------------------------------------------
print("请输入有向图的邻接矩阵:")
n =int(input())#输入矩阵
a = []
print("\n你输入的矩阵为:")
for _ in range(n):
	a.append(list(map(int, input().rstrip().split())))
for i in range(n):
	print(a[i])
x=np.array(a)#利用numpy库将输入的列表转换为numpy中矩阵
value_1=value_2=sum_1=sum_2=sum_3=sum_4=y=final=x#分别定义value_1,sum_1,sum_2等变量(这里代码写的很恶心)
y=x+x.T
#---------------------------------------------------------------------
for i in range(1,n):#计算可达矩阵-此处可参考上图所给出的可达矩阵数学求解方法
    value_1=np.matmul(value_1, x)
    sum_1=sum_1+value_1
sum_2 = sum_1 + np.identity(n)

reachability_matrix=sum_2>0.5#此处将其sum_2矩阵中所有大于0.5的矩阵元素转换为布尔值True,其余元素(均为0)转换为False

print("此有向图的可达矩阵为:")
print(reachability_matrix.astype(int))#得到布尔型矩阵,可将布尔类型数据(True-False)相应转化为数值型(0-1)矩阵-即可达矩阵

final=reachability_matrix+reachability_matrix.T

for i in range(1,n):同上,其实应该编个函数
    value_2=np.matmul(value_2, y)
    sum_3=sum_3+value_2
sum_4 = sum_3 + np.identity(n)
reachability_matrix_1=sum_4>0.5
#---------------------------------------------------------------------
#给出判断结果
if ((reachability_matrix.astype(int)==np.ones((n,n)).astype(int)).all()):
    print("此有向线图G为强连通图或其为无向连通图")
    # print(np.ones((n,n)).astype(int))默认生成全1矩阵其中元素为float型,要多加注意
elif ((final.astype(int)==np.ones((n,n)).astype(int)).all()):
    print("此有向线图G是单向连通图")
elif ((reachability_matrix_1.astype(int)==np.ones((n,n)).astype(int)).all()):
    print("此有向线图G是弱连通图")
else:
    print("此有向图不连通")
#---------------------------------------------------------------------
#下面展示图形化输出有向图G
G = nx.DiGraph()
for i in range(0, n):#标记出标签
        G.add_node(i, desc='v'+str(i))#依次为标签命名

for p in range(0,n):#双重循环扫描并输出所有元素为1的位置
    for q in range(0,n):
        if(x[p,q]==1):
            G.add_edges_from([(p, q)],weight='1')
edge_labels=dict([((u,v,),d['weight'])
                 for u,v,d in G.edges(data=True)])
edge_colors = ['black']
pos=nx.spring_layout(G)#按pos标出结点
node_labels = nx.get_node_attributes(G, 'desc')
nx.draw_networkx_labels(G, pos, labels=node_labels)#画出标签

nx.draw_networkx_edge_labels(G,pos,edge_labels=edge_labels)
nx.draw(G,pos, node_size=1500,edge_color=edge_colors,edge_cmap=plt.cm.Reds)#有向图属性
plt.title('Directed Graph', fontsize=10)#有向图名称
pylab.show()
#嗯嗯嗯,我知道我代码风格不好,别骂了别骂了

给出相应代码实现结果:

     注意相关输入格式:

            [1].第一行输入矩阵的阶数

            [2].后面将相关数据依次按顺序输入矩阵

生成的图形化有向图G(Directed Graph):

最终页面展示:

 

针对编写中容易出现错误的部分,给出相关链接:

[1].如何安装相应模块:  https://blog.csdn.net/qq_43201403/article/details/102336114

[2].关于numpy模块使用的相关文档:   https://www.cnblogs.com/pythonfl/p/12257698.html

[3].networkx模块使用的相关文档: 1.https://blog.csdn.net/your_answer/article/details/79189660 2.https://zhuanlan.zhihu.com/p/40852672

[4].利用netwokx绘图:    https://blog.csdn.net/qq_32284189/article/details/80134768?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-2.control

[5].Python中 all() 与 any() 的区别:https://blog.csdn.net/cython22/article/details/78829288?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-5.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-5.control

最后,如果有相应错误,还请在评论区内多多指出。(代码太渣,轻喷)

来都来了,点个赞再走嘛QWQ

    原文作者:呆猫_NerdyCat
    原文地址: https://blog.csdn.net/weixin_52365731/article/details/117048879
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。