def strongly_connected_components(graph): index_counter = 0 stack = [] lowlinks = {} index = {} result = [] def strongconnect(node, index_counter): index[node] = index_counter lowlinks[node] = index_counter index_counter += 1 stack.append(node) try: successors = graph[node] except: successors = [] # Depth first search for successor in successors: # Does the current node point to a node that was already # visited? if successor not in lowlinks: # Successor has not yet been visited; recurse on it strongconnect(successor, index_counter) lowlinks[node] = min(lowlinks[node],lowlinks[successor]) elif successor in stack: # the successor is in the stack and hence in the # current strongly connected component (SCC) lowlinks[node] = min(lowlinks[node],index[successor]) # If `node` is a root node, pop the stack and generate an SCC if lowlinks[node] == index[node]: connected_component = [] while True: successor = stack.pop() connected_component.append(successor) if successor == node: break component = tuple(connected_component) # storing the result result.append(component) for node in graph: if node not in lowlinks: strongconnect(node, index_counter) return result