def find_cycles(graph): # Record visited nodes in a set, which gives us constant-time lookup of # nodes. visited = set() cycles = [] for node in graph: if node in visited: continue # already been here find_cycles_from_node(graph, node, visited, cycles, []) return cycles def find_cycles_from_node(graph, node, visited, cycles, path): if node in path: # We have found a cycle from the first occurrence of node # to here. # Remove prefix up to the first occurrence: index = path.index(node) cycle = path[index:] cycles.append(cycle) return visited.add(node) path.append(node) length = len(path) for neighbor in graph[node]: # Find cycles forward in graph. find_cycles_from_node(graph, neighbor, visited, cycles, path) # Crop path to prefix up to current node. path = path[:length]