求有向图中以一个顶点V为起止点的所有简单回路(python)

前言

参考链接https://www.cnblogs.com/zhaodongge/p/10680313.html

前段时间在做数学建模题目时遇到了航班任务环的问题,然后去网上查了相关的代码,发现有好几个的都是先找到一个简单路径,然后去结果集中查重,确定该路径不重复后才加入结果集。他的查重认为,回路0→1→2→3(→0)与回路2→3→1→0(→2)是两条相同的回路。个人感觉查重的机制不太适合我要解决的问题,随后就自己写了一个,这个方法还是借鉴了DFS的思想查找图中的简单回路。在DFS访问每一个顶点时,首先将它加入到一个路径暂存数组path中,其次将这个顶点的相邻点入栈,然后通过一个count=[]数组记录这个顶点的出度数,以保证图每个顶点的出度只被用过一次。由于时间有限,我也不好作过多的文字解释,想知道原理的请自行按照程序手动跑一跑,主要注意stack、path、count这三个数组的变化情况即可。希望能帮到大家!


例题:如下面的有向图,求出以A为起止点的所有简单回路(以B、C为起点同理)
在这里插入图片描述


具体代码如下:

#输入:图(邻接表形式)、对图进行DFS的起始顶点V_start
#输出:图中以V_start为起点的所有简单回路

def DFS(graph,startNode):
    stack = []
    stack.append(startNode)
    path=[]#记录当前路径
    ALL_Path=[]#所有路径的结果集
    Path_Name=''#一条路径的名称
    count=[1]#记录每个结点的出度,起始加入一个“1”防止第一次不执行

    while (len(stack) > 0):
    	#若刚加入path数组的顶点V还有出度没有使用过,则进行如下操作
        if count[-1]>0:
            vertex = stack.pop()#访问顶点V的一个邻接顶点M,相当于使用用了一次顶点V的某一个出度
            count[-1]-=1#将顶点V的未使用出度的个数减1
            #若找到一条回路,则将该回路保存至ALL_Path
            if vertex==startNode and len(path)!=0:
                for i in path:
                    Path_Name+=(i+'→')
                Path_Name+=startNode
                ALL_Path.append(Path_Name)
                Path_Name=''
            
            #若被访问顶点M不在当前路径中,则将M加入到路径数组path中,然后将M的邻接顶点入栈、统计M的出度个数加在count数组的后面    
            elif vertex not in path:
                path.append(vertex)
                nodes = graph[vertex]
                count.append(len(nodes))
                for w in nodes:
                    stack.append(w)
        #若刚加入path数组的顶点V的所有出度均使用过,则把顶点V从path数组中移出,相当于进行一个回溯
        else:
            count.pop()
            path.pop()

    #打印以V_start为起点的所有简单回路            
    for i in ALL_Path:
        print(i)
                
if __name__=="__main__":
    a={ 'A':['B','C'],
        'B':['A','C'],
        'C':['A','B'],
       }
    V_start='A'
    DFS(a,V_start)


运行结果如下:
在这里插入图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值