mirror of https://github.com/zeldaret/botw.git
62 lines
1.5 KiB
Python
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
|