一、题目要求:

内容:

对具有n个结点的无向图,判断其能否被一笔画。

要求:

对给定n个结点的无向图,进行欧拉图和半欧拉图的判定,若是欧拉图或半欧拉图,则输出所有的欧拉(回)路。

二、实验原理及内容:

所采用的数据结构:栈(通过python的列表类型pop来模拟)

所采用的的存储结构:字典(存放某一个结点的所有相邻的结点)、集合set(去重+检测是否走过该节点)

函数:

  • def init():
'''函数功能:完成邻接矩阵的初始化'''
  • def GetReachableMatrix(A,n):  #参数A:邻接矩阵  参数n:结点个数
'''函数功能:求可达性矩阵'''
  • def GetOddDegree(matrix,n):
'''函数功能:通过邻接矩阵获取到每一个节点的度数,在保证连通性的前提下,通过奇数度节点直接判别出欧拉路or欧拉回路'''
  • def GetGraph(matrix,n):
''' 函数功能:由邻接矩阵求出一个字典:每一个节点 映射 相邻节点 '''
  • def DFS(graph,start):  #参数 graph是邻接节点的一个字典   参数start是起始点
''' 函数功能:通过dfs算法求出欧拉(回)路 '''


时间复杂度:O(n²)


实验思路:


  • 欧拉(回)路前提:可达性矩阵元素均为1
  • 若不满足1直接结束。若满足:求出奇数度节点的个数,等于2->欧拉路 等于0->欧拉回路
  • 在②的前提下,深度优先搜索,找出一笔画的路径并输出

三、源代码

import numpy as np
from random import randint
'''函数功能:完成邻接矩阵的初始化'''
def init():
     n,m=eval(input("请输入图的结点数和边数(逗号隔开):"))
     matrix = np.zeros((n, n), dtype=int)  #图的邻接矩阵
     m_list=(input("请输入有关联关系的两个结点1,3(每一对中间用空格隔开):例如  1,5 1,6 在无向图中表示结点1和节点5、6是相互可达的\n")).split(' ')
     for i in m_list:    #根据用户的输入,完成邻接矩阵的初始化
          matrix[eval(i[0])-1,eval(i[-1])-1]=1;
          matrix[eval(i[-1])-1, eval(i[0])-1] = 1; #无向图的邻接矩阵是对称的    减去1是为了与矩阵的下标对应
     return matrix,n

'''函数功能:求可达性矩阵'''
def GetReachableMatrix(A,n):  #参数A:邻接矩阵  参数n:结点个数
     temp = np.array(A, dtype=int)
     C=np.zeros((n,n),dtype=int)  #B是可达性矩阵
     for i in range(n):
          C+=temp
          temp=np.dot(temp,A)
     t=np.array(C,dtype=bool)
     B=np.array(t,dtype=int)
     return B

'''函数功能:通过邻接矩阵获取到每一个节点的度数,在保证连通性的前提下,通过奇数度节点直接判别出欧拉路or欧拉回路'''
def GetOddDegree(matrix,n):
     count=0 #表示奇数度的大小
     for i in range(n):
          sum=0
          for j in range(n):
               sum+=matrix[i][j]
          if sum%2 !=0:# 说明是奇数
               count+=1
     return count

''' 函数功能:由邻接矩阵求出一个字典:每一个节点 映射 相邻节点 '''
def GetGraph(matrix,n):
     graph=dict()  #生成一个空字典
     for i in range(n):
          graph["v"+str(i+1)]=list()#映射的对象是一个列表
          for j in range(n):
               if matrix[i][j]==1:
                    #向列表中添加邻接节点
                    graph["v"+str(i+1)].append("v"+str(j+1))
     return graph

def DFS(graph,start):  #参数 graph是邻接节点的一个字典   参数start是起始点
     stack=[]  #当栈用
     seen=set() #创建一个集合,查重用(判断这条路是否已经走过)+记录路径的作用
     print("一笔画路径为:",end="")
     stack.append(start)
     seen.add(start)
     while (len(stack)>0):
          vertx=stack.pop()  #默认是从栈顶取出
          node=graph[vertx]
          for i in node:
               if i not in seen:#确保之前没有走过该节点
                    stack.append(i)
                    seen.add(i)
          print(vertx+"->",end="")
     print("\b\b")

if __name__=='__main__':
     matrix,Node=init()  #initial info
     templateMatrix=np.ones((Node,Node),dtype=int)  #连通性阵的可达性矩阵的模板 全是1 用于比较
     ReachhableMatrix=GetReachableMatrix(matrix,Node)  #求可达性矩阵
     graph=GetGraph(matrix,Node)    #得到每一个节点的邻接节点构成的字典dict
     r=randint(0,Node)
     print("邻接矩矩阵为:\n",matrix)

     if (templateMatrix==ReachhableMatrix).all():
          if GetOddDegree(matrix,Node)==0:#奇数度节点为0个,说明是欧拉图
               DFS(graph, "v"+str(Node))
               print("是欧拉图-->可以一笔画")
          elif GetOddDegree(matrix,Node):
               DFS(graph, "v"+str(Node))
               print("是半欧拉图-->可以一笔画")
          else:
               print("既不是欧拉路,也不是欧拉回路-->不能一笔画")
     else:
          print("非连通图,既不是半欧拉图,也不是欧拉图-->不能一笔画")

四、写在最后

python将离散数据转化为连续数据 python 离散数学_算法

https://www.bilibili.com/video/BV1ts41157Sy?spm_id_from=333.1007.top_right_bar_window_default_collection.content.click