def eulerian_path(G: DirectedGraph) -> list: """ Find eulerian path in the given graph Args: graph to find eulerian path in Return: path if found or None if not found """ cycle = eulerian_cycle(G) if cycle is not None: return cycle in_edges = [0] * G.V() out_edges = [0] * G.V() for u in range(G.V()): for v, c in G.adj(u): in_edges[v] += c out_edges[u] += c # start vertex s = -1 cnt = 0 for v in range(G.V()): if (in_edges[v] + out_edges[v]) % 2 == 1: cnt += 1 if cnt > 2: return None if s == -1 or out_edges[s] % 2 == 0: s = v if s == -1: return None G = deepcopy(G) E = G.E() tour = [] cur = s while True: try: tour.append(cur) (v, c) = G.adj(cur).__next__() G.remove_edge(DirectedEdge(cur, v)) cur = v except StopIteration: break def selfloop(u: int): nonlocal G path = [] cur = u while cur != u or not path: path.append(cur) (v, c) = G.adj(cur).__next__() G.remove_edge(DirectedEdge(cur, v)) cur = v path.append(u) return path index = 0 while index < len(tour): try: G.adj(tour[index]).__next__() tour = tour[:index] + selfloop(tour[index]) + tour[index + 1:] except StopIteration: index += 1 return tour if len(tour) == E + 1 else None
#!/usr/bin/env python3 from common import IO from graph.directed import Graph, GraphMatrix from graph import algorithm io = IO() G = Graph.fromfile(io.filein) G_matrix = GraphMatrix.from_graph(G) # Eulerian cycle, part 1 io.section('Eulerian cycle') eulerian_cycle = algorithm.eulerian_cycle(G_matrix) if eulerian_cycle is not None: io.print('Eulerian cycle found: ') io.print_path(eulerian_cycle) else: io.print('Eulerian cycle not found!') # Eulerian path, part 2 io.section('Eulerian path') eulerian_path = algorithm.eulerian_path(G_matrix) if eulerian_path is not None: io.print('Eulerian path found: ') io.print_path(eulerian_path) else: io.print('Eulerian path not found!') # Hamiltonian cycle, part 1 io.section('Hamiltonian cycle')