⚠️ 缩完之后合法顺序反而变少了
把上一节那张有环的图缩点:每个强连通分量捏成一个点,分量之间的边保留(去掉重边和自环)。n01 里那张 DAG 有 4 种合法顺序。缩点之后的这张图有几种?两个数一起输出:
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)
from itertools import permutations
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]})
M = len(gs)
cnt = sum(1 for p in permutations(range(M))
if all(p.index(a) < p.index(b) for a, b in ce))
print(str(4) + "/" + str(cnt))
全部评论