acl_cpp.scc
scc.scc_graph
# scc_graph
from acl_cpp.scc import scc_graph
Decomposes a directed graph into strongly connected components.
Constructor
# scc_graph::scc_graph(int n)
def scc_graph(n: int = 0) -> scc_graph
Creates a graph with \(n\) vertices and \(0\) edges.
Constraints
\(0 \le n < 2^{31}\)
Complexity
\(O(n)\)
scc_graph.add_edge
# void scc_graph::add_edge(int from, int to)
def scc_graph.add_edge(from_: int, to: int) -> None
Adds an edge from vertex \(\mathit{from\_}\) to vertex \(\mathit{to}\).
Constraints
\(0 \le \mathit{from\_} < n\)
\(0 \le \mathit{to} < n\)
Complexity
Amortized \(O(1)\)
scc_graph.scc
# vector<vector<int>> scc_graph::scc()
def scc_graph.scc() -> list[list[int]]
Returns a list of lists of vertices that satisfy the following conditions:
Each vertex appears in exactly one of the lists.
Each inner list corresponds to a strongly connected component. The order of vertices within each list is undefined.
The lists are topologically sorted. i.e., for vertices \(u\) and \(v\) in different strongly connected components, if there exists a directed path from \(u\) to \(v\), the list containing \(u\) appears earlier the list containing \(v\).
Complexity
Let \(m\) be the number of edges added, then
\(O(n + m)\)
Examples
AC code of https://atcoder.jp/contests/practice2/tasks/practice2_g
from acl_cpp.scc import scc_graph
N, M = map(int, input().split())
g = scc_graph(N)
for _ in range(M):
u, v = map(int, input().split())
g.add_edge(u, v)
scc = g.scc()
print(len(scc))
for component in scc:
print(len(component), *component)