缩完还剩几个点几条边
把上一节那张有环的图缩点:每个强连通分量捏成一个点,分量之间的边保留(去掉重边和自环)。原图是七个点八条边。
G = [(0, 1), (0, 2), (1, 3), (2, 3), (3, 4), (4, 5), (5, 3), (4, 6)]
N = 7
def build(edges):
g = {u: [] for u in range(N)}
for a, b in edges:
g[a].append(b)
for u in g:
g[u].sort()
return g
def kosaraju(edges, second_reversed=True):
g = build(edges)
rg = build([(b, a) for a, b in edges])
seen, order = set(), []
for s in range(N):
if s in seen:
continue
st = [(s, iter(g[s]))]
seen.add(s)
while st:
u, it = st[-1]
for v in it:
if v not in seen:
seen.add(v)
st.append((v, iter(g[v])))
break
else:
order.append(u)
st.pop()
second = rg if second_reversed else g
seen2, groups = set(), []
for s in reversed(order):
if s in seen2:
continue
st, grp = [s], []
seen2.add(s)
while st:
u = st.pop()
grp.append(u)
for v in second[u]:
if v not in seen2:
seen2.add(v)
st.append(v)
groups.append(sorted(grp))
return sorted(groups)
gs = kosaraju(G)
comp = {}
for i, grp in enumerate(gs):
for u in grp:
comp[u] = i
ce = sorted({(comp[a], comp[b]) for a, b in G if comp[a] != comp[b]})
print(str(len(gs)) + "/" + str(len(ce)))
全部评论