123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 |
- # Tarjan's strongly connected components algorithm
- # Taken from https://stackoverflow.com/a/6575693 and adopted to Python3
- from itertools import chain
- from collections import defaultdict
- from typing import *
- Edge = Tuple[Any,Any]
- class _Graph:
- def __init__(self, edges: List[Edge]):
- edges = list(list(x) for x in edges)
- self.edges = edges
- self.vertices = set(chain(*edges))
- self.tails = defaultdict(list)
- for head, tail in self.edges:
- self.tails[head].append(tail)
- def strongly_connected_components(edges: List[Edge]):
- graph = _Graph(edges)
- counter = 0
- count = dict()
- lowlink = dict()
- stack = []
- connected_components = []
- def strong_connect(head):
- nonlocal counter
- lowlink[head] = count[head] = counter = counter + 1
- stack.append(head)
- for tail in graph.tails[head]:
- if tail not in count:
- strong_connect(tail)
- lowlink[head] = min(lowlink[head], lowlink[tail])
- elif count[tail] < count[head]:
- if tail in stack:
- lowlink[head] = min(lowlink[head], count[tail])
- if lowlink[head] == count[head]:
- component = []
- while stack and count[stack[-1]] >= count[head]:
- component.append(stack.pop())
- connected_components.append(component)
- for v in graph.vertices:
- if v not in count:
- strong_connect(v)
- return connected_components
|