Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
85
Task/Tarjan/Python/tarjan-2.py
Normal file
85
Task/Tarjan/Python/tarjan-2.py
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
from collections import defaultdict
|
||||
|
||||
|
||||
class Graph:
|
||||
"Directed Graph Tarjan's strongly connected components algorithm"
|
||||
|
||||
def __init__(self, name, connections):
|
||||
self.name = name
|
||||
self.connections = connections
|
||||
g = defaultdict(list) # map node vertex to direct connections
|
||||
for n1, n2 in connections:
|
||||
if n1 != n2:
|
||||
g[n1].append(n2)
|
||||
else:
|
||||
g[n1]
|
||||
for _, n2 in connections:
|
||||
g[n2] # For leaf nodes having no edges from themselves
|
||||
self.graph = dict(g)
|
||||
self.tarjan_algo()
|
||||
|
||||
def _visitor(self, this, low, disc, stack):
|
||||
'''
|
||||
Recursive function that finds SCC's
|
||||
using DFS traversal of vertices.
|
||||
|
||||
Arguments:
|
||||
this --> Vertex to be visited in this call.
|
||||
disc{} --> Discovery order of visited vertices.
|
||||
low{} --> Connected vertex of earliest discovery order
|
||||
stack --> Ancestor node stack during DFS.
|
||||
'''
|
||||
|
||||
disc[this] = low[this] = self._order
|
||||
self._order += 1
|
||||
stack.append(this)
|
||||
|
||||
for neighbr in self.graph[this]:
|
||||
if neighbr not in disc:
|
||||
# neighbour not visited so do DFS recurrence.
|
||||
self._visitor(neighbr, low, disc, stack)
|
||||
low[this] = min(low[this], low[neighbr]) # Prior connection?
|
||||
|
||||
elif neighbr in stack:
|
||||
# Update low value of this only if neighbr in stack
|
||||
low[this] = min(low[this], disc[neighbr])
|
||||
|
||||
if low[this] == disc[this]:
|
||||
# Head node found of SCC
|
||||
top, new = None, []
|
||||
while top != this:
|
||||
top = stack.pop()
|
||||
new.append(top)
|
||||
self.scc.append(new)
|
||||
|
||||
def tarjan_algo(self):
|
||||
'''
|
||||
Recursive function that finds strongly connected components
|
||||
using the Tarjan Algorithm and function _visitor() to visit nodes.
|
||||
'''
|
||||
|
||||
self._order = 0 # Visitation order counter
|
||||
disc, low = {}, {}
|
||||
stack = []
|
||||
|
||||
self.scc = [] # SCC result accumulator
|
||||
for vertex in sorted(self.graph):
|
||||
if vertex not in disc:
|
||||
self._visitor(vertex, low, disc, stack)
|
||||
self._disc, self._low = disc, low
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
for n, m in [('Tx1', '10 02 21 03 34'.split()),
|
||||
('Tx2', '01 12 23'.split()),
|
||||
('Tx3', '01 12 20 13 14 16 35 45'.split()),
|
||||
('Tx4', '01 03 12 14 20 26 32 45 46 56 57 58 59 64 79 89 98 AA'.split()),
|
||||
('Tx5', '01 12 23 24 30 42'.split()),
|
||||
]:
|
||||
print(f"\n\nGraph({repr(n)}, {m}):\n")
|
||||
g = Graph(n, m)
|
||||
print(" : ", ' '.join(str(v) for v in sorted(g._disc)))
|
||||
print(" DISC of", g.name + ':', [v for _, v in sorted(g._disc.items())])
|
||||
print(" LOW of", g.name + ':', [v for _, v in sorted(g._low.items())])
|
||||
scc = repr(g.scc if g.scc else '').replace("'", '').replace(',', '')[1:-1]
|
||||
print("\n SCC's of", g.name + ':', scc)
|
||||
Loading…
Add table
Add a link
Reference in a new issue