G002 Tarjan算法如何识别CF999E首都可达性强连通分量?

摘要:CF999E Reachability from the Capital - CodeForces 给定一个有向图和一个节点 (s) ,问最少加多少条边可以使 (s) 可以到达图中所有的点( (s) 可以到达自身) 考虑缩点,缩
CF999E Reachability from the Capital - CodeForces 给定一个有向图和一个节点 \(s\) ,问最少加多少条边可以使 \(s\) 可以到达图中所有的点( \(s\) 可以到达自身) 考虑缩点,缩点后源点一定被无法到达,所以我们需要统计源点的个数。 特判,当 \(s\) 在其中一个源点中时,这时应该少加一条边。 import sys sys.setrecursionlimit(10000) if 1: inp = lambda: sys.stdin.readline().strip() II = lambda: int(inp()) MII = lambda: map(int, inp().split()) LII = lambda: list(MII()) Max = lambda x, y: x if x > y else y Min = lambda x, y: x if x < y else y def main(): n, m, s = MII() g = [[] for _ in range(n + 1)] for _ in range(m): u, v = MII() g[u].append(v) dfn = [-1] * (n + 1) low = [-1] * (n + 1) st = [] inst = [False] * (n + 1) scc_id = [-1] * (n + 1) scc = 0 timer = 1 def tarjan(x): nonlocal timer, scc dfn[x] = low[x] = timer timer += 1 st.append(x) inst[x] = True for y in g[x]: if dfn[y] == -1: tarjan(y) low[x] = Min(low[x], low[y]) elif inst[y]: low[x] = Min(low[x], dfn[y]) if dfn[x] == low[x]: while True: cur = st.pop() inst[cur] = False scc_id[cur] = scc if cur == x: break scc += 1 for i in range(1, n + 1): if dfn[i] == -1: tarjan(i) din = [0] * scc for u in range(1, n + 1): for v in g[u]: if scc_id[u] != scc_id[v]: din[scc_id[v]] += 1 cnt = sum(1 for i in range(scc) if din[i] == 0) print(cnt - 1 if din[scc_id[s]] == 0 else cnt) if __name__ == "__main__": main()