43 lines
1.3 KiB
Python
43 lines
1.3 KiB
Python
import sys, os
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
from scc import scc
|
|
|
|
def tarjan_recursive(adj):
|
|
idx=[0]; stack=[]; on=set(); indices={}; low={}; res=[]
|
|
import sys as _s
|
|
_s.setrecursionlimit(100000)
|
|
def strong(v):
|
|
indices[v]=low[v]=idx[0]; idx[0]+=1; stack.append(v); on.add(v)
|
|
for w in adj.get(v,()):
|
|
if w not in indices:
|
|
strong(w); low[v]=min(low[v],low[w])
|
|
elif w in on: low[v]=min(low[v],indices[w])
|
|
if low[v]==indices[v]:
|
|
comp=[]
|
|
while True:
|
|
w=stack.pop(); on.discard(w); comp.append(w)
|
|
if w==v: break
|
|
res.append(comp)
|
|
for u in list(adj):
|
|
if u not in indices: strong(u)
|
|
return res
|
|
|
|
import random
|
|
random.seed(42)
|
|
for trial in range(200):
|
|
n=random.randint(1,40)
|
|
adj={i:[] for i in range(n)}
|
|
for i in range(n):
|
|
for j in range(n):
|
|
if random.random()<0.25: adj[i].append(j)
|
|
a=sorted(sorted(c) for c in scc(adj))
|
|
b=sorted(sorted(c) for c in tarjan_recursive(adj))
|
|
assert a==b, (a,b)
|
|
print("ALL 200 RANDOM TRIALS PASSED")
|
|
# big graph no recursion
|
|
N=200000
|
|
adj={i:[i+1] for i in range(N-1)}
|
|
adj[N-1]=[0]
|
|
r=scc(adj)
|
|
assert len(r)==1 and len(r[0])==N
|
|
print("BIG CYCLE OK", len(r[0])) |