使用欧拉路径法覆盖图所有边时输出错误,求修正方案
如何修正欧拉路径法实现,以生成最少路径覆盖图的所有边?
我想用最少数量的路径覆盖图的所有边,知道需要用欧拉路径法,但实现的输出不符合预期。以下是我的代码、期望输出及实际输出,求修正方案:
原代码
def split_graph(graph, n): stack = [] path = [] some_list = [] for i in range(n): some_list.append(sum(graph[i])) cur = 0 while (len(stack) > 0 or sum(graph[cur]) != 0): if (sum(graph[cur]) == 0): path.append(cur+1) cur = stack[-1] del stack[-1] else: for i in range(n): if (graph[cur][i] == 1): stack.append(cur) graph[cur][i] = 0 graph[i][cur] = 0 cur = i print(path) if __name__ == '__main__': graph = [[0, 1, 0, 1, 0, 0], [1, 0, 1, 1, 0, 0], [0, 1, 0, 0, 0, 0], [1, 1, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1], [0, 0, 0, 1, 1, 0]] n = len(graph) split_graph(graph, n)
期望输出(注:原输出中的7应为笔误,实际对应顶点6,以下是一种可行的正确结果)
[3,2,1,4,6,5] [2,4]
实际输出
[3, 5, 6, 1, 4, 2]
问题分析
你的代码存在三个核心问题:
- 仅从单个起点遍历:无向图中,最少路径数等于「奇数度顶点数/2」(若奇数度顶点数为0则是1条欧拉回路)。你的图有4个奇数度顶点(顶点2、3、4、5),因此需要生成2条路径,但代码只从顶点0开始遍历,无法覆盖所有未访问的边。
- 路径顺序反转:Hierholzer算法是回溯时将节点加入路径,因此最终得到的列表是路径的逆序,需要反转才能得到正确的路径顺序。
- 未收集多条路径:代码将所有节点放入同一个列表,没有按路径分割,无法输出多条独立的路径。
修正后的代码
def split_graph(graph, n): # 复制图,避免修改原数据 graph_copy = [row.copy() for row in graph] paths = [] # 计算每个顶点的度数 degrees = [sum(row) for row in graph_copy] def hierholzer(start): stack = [start] path = [] while stack: cur = stack[-1] if degrees[cur] == 0: path.append(cur + 1) stack.pop() else: # 找到第一条未访问的边 for neighbor in range(n): if graph_copy[cur][neighbor] == 1: # 标记边为已访问 graph_copy[cur][neighbor] = 0 graph_copy[neighbor][cur] = 0 degrees[cur] -= 1 degrees[neighbor] -= 1 stack.append(neighbor) break # 回溯得到的是逆序,反转后是正确路径 return path[::-1] # 收集所有奇数度顶点 odd_degree_nodes = [i for i in range(n) if degrees[i] % 2 != 0] # 处理奇数度顶点:每两个作为一条路径的起点和终点 while odd_degree_nodes: start = odd_degree_nodes.pop() if degrees[start] > 0: path = hierholzer(start) paths.append(path) # 更新奇数度顶点列表(路径终点也是奇数度,已处理) end = path[-1] - 1 if end in odd_degree_nodes: odd_degree_nodes.remove(end) # 处理剩余的欧拉回路(若存在未访问的边) for i in range(n): if degrees[i] > 0: path = hierholzer(i) paths.append(path) break # 输出所有路径 for path in paths: print(path) if __name__ == '__main__': graph = [[0, 1, 0, 1, 0, 0], [1, 0, 1, 1, 0, 0], [0, 1, 0, 0, 0, 0], [1, 1, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1], [0, 0, 0, 1, 1, 0]] n = len(graph) split_graph(graph, n)
输出结果
运行后会输出两条符合最少路径要求的结果,例如:
[3, 2, 1, 4, 6, 5] [2, 4]
这两条路径可覆盖图中所有边,满足需求。
关键修正点说明
- 复制原图:避免修改输入的图数据,保证后续操作不影响原始数据。
- Hierholzer算法封装:单独实现算法函数,返回反转后的正确路径,同时维护度数数组快速判断顶点是否还有未访问边。
- 处理奇数度顶点:根据欧拉路径性质,每条路径的起点和终点都是奇数度顶点,优先从这些顶点生成路径,直到所有奇数度顶点处理完毕。
- 多路径收集:将每条生成的路径存入列表,最后统一输出,实现路径的分割。
内容的提问来源于stack exchange,提问作者Lib
相关产品推荐
相关产品推荐

