botw/tools/util/graph.py

62 lines
1.5 KiB
Python

from collections import defaultdict
_Visiting = 0
_Visited = 1
class Graph:
def __init__(self):
self.nodes = defaultdict(set)
def add_edge(self, a, b):
self.nodes[a].add(b)
def find_connected_components(self):
nodes = defaultdict(list)
for u in self.nodes:
for v in self.nodes[u]:
nodes[u].append(v)
nodes[v].append(u)
cc = []
visited = set()
def dfs(start):
result = []
to_visit = [start]
while to_visit:
x = to_visit.pop()
result.append(x)
visited.add(x)
for y in nodes[x]:
if y not in visited:
to_visit.append(y)
return result
for u in nodes.keys():
if u in visited:
continue
cc.append(dfs(u))
return cc
def topological_sort(self) -> list:
result = []
statuses = dict()
def dfs(node):
if statuses.get(node) == _Visiting:
raise RuntimeError("Graph is not acyclic")
if statuses.get(node) == _Visited:
return
statuses[node] = _Visiting
for y in self.nodes.get(node, set()):
dfs(y)
statuses[node] = _Visited
result.insert(0, node)
for x in self.nodes:
dfs(x)
return result