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)