Problem:


Score : 100 points

Problem Statement

You are given a directed graph with N vertices and M edges, not necessarily simple. The i-th edge is oriented from the vertex a_i to the vertex b_i.
Divide this graph into strongly connected components and print them in their topological order.

Constraints

1 \leq N \leq 500,000

1 \leq M \leq 500,000

0 \leq a_i, b_i < N

Input

Input is given from Standard Input in the following format:

N M
a_0 b_0
a_1 b_1
:
a_{M - 1} b_{M - 1}

Output

Print 1+K lines, where K is the number of strongly connected components.
Print K on the first line. 
Print the information of each strongly connected component in next K lines in the following format, where l is the number of vertices in the strongly connected component and v_i is the index of the vertex in it.

l v_0 v_1 ... v_{l-1}

Here, for each edge (a_i, b_i), b_i should not appear in earlier line than a_i.

If there are multiple correct output, print any of them.

Sample Input 1

6 7
1 4
5 2
3 0
5 5
4 1
0 3
4 2

Sample Output 1

4
1 5
2 4 1
1 2
2 3 0



Sample input:
6 7
1 4
5 2
3 0
5 5
4 1
0 3
4 2


Sample output:
4
1 5
2 4 1
1 2
2 3 0

Submission status: Accepted

Solution code:
import sys
readline = sys.stdin.readline
#非再帰
import sys
def scc(Edge):
    N = len(Edge)
    Edgeinv = [[] for _ in range(N)]
    for vn in range(N):
        for vf in Edge[vn]:
            Edgeinv[vf].append(vn)
    
    used = [0]*N
    order = []
    for st in range(N):
        if used[st]:
            continue
        stack = [~st, st]
        while stack:
            vn = stack.pop()
            if vn >= 0:
                if used[vn]:
                    continue
                used[vn] = 1
                for vf in Edge[vn]:
                    if used[vf]:
                        continue
                    stack.append(~vf)
                    stack.append(vf)
            else:
                if used[~vn] != 2:
                    used[~vn] = 2
                    order.append(~vn)


    res = [None]*N
    used = [False]*N
    cnt = -1
    for st in order[::-1]:
        if not used[st]:
            cnt += 1
            stack = [st]
            res[st] = cnt
            used[st] = True
            while stack:
                vn = stack.pop()
                for vf in Edgeinv[vn]:
                    if not used[vf]:
                        used[vf] = True
                        res[vf] = cnt
                        stack.append(vf)
    M = cnt+1
    components = [[] for _ in range(M)]
    for i in range(N):
        components[res[i]].append(i)
    """
    tEdge = [[] for _ in range(M)]
    teset = set()
    for vn in range(N):
        tn = res[vn]
        for vf in Edge[vn]:
            tf = res[vf]
            if tn != tf and tn*M + tf not in teset:
                teset.add(tn*M + tf)
                tEdge[tn].append(tf)
    """
    return res, components


        
N, M = map(int, readline().split())
Edge = [[] for _ in range(N)]
for _ in range(M):
    a, b = map(int, readline().split())
    Edge[a].append(b)

R, comp = scc(Edge)
Ans = [str(len(comp))]

for c in comp:
    Ans.append(f'{len(c)} ' + ' '.join(map(str, c)))

print('\n'.join(Ans))

Submission status: Accepted

Solution code:
import sys
sys.setrecursionlimit(1000000)
n,m=map(int, input().split())
e=[[] for _ in range(n)]
e_rev=[[] for _ in range(n)]
for i in range(m):
    ai,bi=map(int, input().split())
    e[ai].append(bi)
    e_rev[bi].append(ai)

p_ord=[]
used=[0]*n
def dfs(v):
    used[v]=1
    for u in e[v]:
        if not used[u]:
            dfs(u)
    p_ord.append(v)
for i in range(n):
    if not used[i]:
        dfs(i)
compo = [0]*n
used=[0]*n
def dfs_rev(v,c):
    compo[v]=c
    used[v]=1
    for u in e_rev[v]:
        if not used[u]:
            dfs_rev(u,c)
cnt=0
for i in reversed(p_ord):
    if not used[i]:
        dfs_rev(i,cnt)
        cnt+=1
cc=[[] for _ in range(cnt+1)]
for i in range(n):
    cc[compo[i]].append(i)

print(len([cci for cci in cc if cci]))
for cci in cc:
    if cci:
        print(len(cci),*cci)

Submission status: Accepted

Solution code:
import sys
input = sys.stdin.readline

def dfs_numbering(st, M, V, ANS, cnt, v):
    ST = [st]
    while len(ST) > 0:
        i = ST[-1]
        if ANS[i] == -1:
            V[i] = v
            end = 1
            for x in M[i]:
                if V[x] == -1:
                    ST.append(x)
                    end = 0
            if end == 1:
                ST.pop()
                ANS[i] = cnt
                cnt += 1
        else:
            ST.pop()
    return cnt

class scc():
    def __init__(self, n):
        self.n = n
        self.M = [[] for i in range(n)]
        self.IM = [[] for i in range(n)]

    def add_edge(self, frm, to):
        self.M[frm].append(to)
        self.IM[to].append(frm)

    def scc_list(self):
        n = self.n
        V = [-1] * n
        ANS = [-1] * n

        cnt = 0
        for i in range(n):
            if V[i] == -1:
                cnt = dfs_numbering(i, self.M, V, ANS, cnt, 0)

        ANS1 = [[ANS[i], i] for i in range(n)]
        ANS1.sort(reverse=True)

        V = [-1] * n
        ANS = [-1] * n
        v = 0
        for i in range(n):
            if V[ANS1[i][1]] == -1:
                dfs_numbering(ANS1[i][1], self.IM, V, ANS, 0, v)
                v += 1

        FANS = [[] for i in range(v)]
        for i in range(n):
            FANS[V[i]].append(i)

        return FANS

n, m = map(int,input().split())

S = scc(n)
for i in range(m):
    frm, to = map(int,input().split())
    S.add_edge(frm, to)
ANS = S.scc_list()

print(len(ANS))
for i in range(len(ANS)):
    print(len(ANS[i]), end=" ")
    print(*ANS[i])

Submission status: Accepted

Solution code:
import sys
input = sys.stdin.readline

sys.setrecursionlimit(10**6 + 5)

def dfs_numbering(st, M, V, ANS, cnt, v):
    ST = [st]
    while len(ST) > 0:
        # print(ST,V)
        i = ST[-1]
        if ANS[i] == -1:
            V[i] = v
            end = 1
            for x in M[i]:
                if V[x] == -1:
                    ST.append(x)
                    end = 0
                    # cnt = dfs_numbering(x, M, V, ANS, cnt, v)
            if end == 1:
                ST.pop()
                ANS[i] = cnt
                cnt += 1
        else:
            ST.pop()
    return cnt

class scc():
    def __init__(self, n):
        self.n = n
        self.M = [[] for i in range(n)]
        self.IM = [[] for i in range(n)]

    def add_edge(self, frm, to):
        self.M[frm].append(to)
        self.IM[to].append(frm)

    def scc_list(self):
        n = self.n
        V = [-1] * n
        ANS = [-1] * n

        cnt = 0
        for i in range(n):
            if V[i] == -1:
                cnt = dfs_numbering(i, self.M, V, ANS, cnt, 0)

        # print(ANS)

        ANS1 = [[ANS[i], i] for i in range(n)]
        ANS1.sort(reverse=True)

        # print(ANS1)

        V = [-1] * n
        ANS = [-1] * n
        v = 0
        for i in range(n):
            if V[ANS1[i][1]] == -1:
                dfs_numbering(ANS1[i][1], self.IM, V, ANS, 0, v)
                v += 1

        FANS = [[] for i in range(v)]
        for i in range(n):
            FANS[V[i]].append(i)

        return FANS

n, m = map(int,input().split())

S = scc(n)
for i in range(m):
    frm, to = map(int,input().split())
    S.add_edge(frm, to)
ANS = S.scc_list()

print(len(ANS))
for i in range(len(ANS)):
    print(len(ANS[i]), end=" ")
    print(*ANS[i])

Submission status: Accepted

Solution code:
N,M = map(int,input().split())
AB = [tuple(map(int,input().split())) for i in range(M)]

import sys
sys.setrecursionlimit(10**8)
class Scc:
    def __init__(self,n):
        self.n = n
        self.edges = []

    def add_edge(self,fr,to):
        assert 0 <= fr < self.n
        assert 0 <= to < self.n
        self.edges.append((fr, to))

    def scc(self):
        csr_start = [0] * (self.n + 1)
        csr_elist = [0] * len(self.edges)
        for fr,to in self.edges:
            csr_start[fr + 1] += 1
        for i in range(1,self.n+1):
            csr_start[i] += csr_start[i-1]
        counter = csr_start[:]
        for fr,to in self.edges:
            csr_elist[counter[fr]] = to
            counter[fr] += 1

        self.now_ord = self.group_num = 0
        self.visited = []
        self.low = [0] * self.n
        self.ord = [-1] * self.n
        self.ids = [0] * self.n
        def _dfs(v):
            self.low[v] = self.ord[v] = self.now_ord
            self.now_ord += 1
            self.visited.append(v)
            for i in range(csr_start[v], csr_start[v+1]):
                to = csr_elist[i]
                if self.ord[to] == -1:
                    _dfs(to)
                    self.low[v] = min(self.low[v], self.low[to])
                else:
                    self.low[v] = min(self.low[v], self.ord[to])
            if self.low[v] == self.ord[v]:
                while 1:
                    u = self.visited.pop()
                    self.ord[u] = self.n
                    self.ids[u] = self.group_num
                    if u==v: break
                self.group_num += 1
        for i in range(self.n):
            if self.ord[i] == -1: _dfs(i)
        for i in range(self.n):
            self.ids[i] = self.group_num - 1 - self.ids[i]

        groups = [[] for _ in range(self.group_num)]
        for i in range(self.n):
            groups[self.ids[i]].append(i)
        return groups

scc = Scc(N)
for a,b in AB:
    scc.add_edge(a,b)
ans = scc.scc()
print(len(ans))
for row in ans:
    print(*[len(row)] + row)

Submission status: Accepted

Solution code:

from collections import defaultdict

def scc(V, E):
    g = defaultdict(list)
    rg = defaultdict(list)
    for u, v in E:
        g[u].append(v)
        rg[v].append(u)


    o = []
    done = set()
    for u in V:
        if u in done:
            continue

        s = [(u, True)]
        while s:
            u, f = s.pop()
            if f:
                if u in done:
                    continue
                done.add(u)
                s.append((u, False))
                for v in g[u]:
                    if v in done:
                        continue
                    s.append((v, True))
            else:
                o.append(u)

    done = set()
    ans = []
    while o:
        u = o.pop()
        if u in done:
            continue

        s = [u]
        vv = [u]
        done.add(u)
        while s:
            u = s.pop()
            for v in rg[u]:
                if v in done:
                    continue
                vv.append(v)
                s.append(v)
                done.add(v)
        ans.append(vv)


    return ans


def atcoder_practice2_g():
    # https://atcoder.jp/contests/practice2/submissions/16819240
    import sys
    input = sys.stdin.buffer.readline
    N, M = map(int, input().split())

    E = []
    for _ in range(M):
        a, b = map(int, input().split())
        E.append((a, b))
    V = list(range(N))
    vv = scc(V, E)
    print(len(vv))
    for r in vv:
        print(len(r), *r)


if __name__ == "__main__":
    atcoder_practice2_g()

Submission status: Accepted

Solution code:

from collections import defaultdict
import sys

input = sys.stdin.buffer.readline

def scc(V, E):
    g = defaultdict(list)
    # g = [[] for _ in range(len(V))]
    rg = defaultdict(list)
    # rg = [[] for _ in range(len(V))]
    for u, v in E:
        g[u].append(v)
        rg[v].append(u)


    o = []
    done = set()
    for u in V:
        if u in done:
            continue

        s = [(u, True)]
        while s:
            u, f = s.pop()
            if f:
                if u in done:
                    continue
                done.add(u)
                s.append((u, False))
                for v in g[u]:
                    if v in done:
                        continue
                    s.append((v, True))
            else:
                o.append(u)

    done = set()
    ans = []
    while o:
        u = o.pop()
        if u in done:
            continue

        s = [u]
        vv = [u]
        done.add(u)
        while s:
            u = s.pop()
            for v in rg[u]:
                if v in done:
                    continue
                vv.append(v)
                s.append(v)
                done.add(v)
        ans.append(vv)


    return ans


def atcoder_practice2_g():
    N, M = map(int, input().split())

    E = []
    for _ in range(M):
        a, b = map(int, input().split())
        E.append((a, b))
    V = list(range(N))
    vv = scc(V, E)
    print(len(vv))
    for r in vv:
        print(len(r), *r)


def test():
    g = {
        1: [2],
        5: [2],
        2: [4, 3],
        3: [4, 7, 6],
        4: [5, 8],
        6: [9],
        7: [8],
        8: [9],
        9: [7, 10],
        10: []
    }

    V = list(range(1, 11))
    E = []
    for u, e in g.items():
        for v in e:
            E.append((u, v))

    vv = scc(V, E)
    for r in vv:
        print(r)


if __name__ == "__main__":
    # test()
    atcoder_practice2_g()

Submission status: Accepted

Solution code:

from collections import defaultdict
import sys

input = sys.stdin.buffer.readline

def scc(V, E):
    # g = defaultdict(list)
    g = [[] for _ in range(len(V))]
    # rg = defaultdict(list)
    rg = [[] for _ in range(len(V))]
    for u, v in E:
        g[u].append(v)
        rg[v].append(u)


    o = []
    done = set()
    for u in V:
        if u in done:
            continue

        s = [(u, True)]
        while s:
            u, f = s.pop()
            if f:
                if u in done:
                    continue
                done.add(u)
                s.append((u, False))
                for v in g[u]:
                    if v in done:
                        continue
                    s.append((v, True))
            else:
                o.append(u)

    done = set()
    ans = []
    while o:
        u = o.pop()
        if u in done:
            continue

        s = [u]
        vv = [u]
        done.add(u)
        while s:
            u = s.pop()
            for v in rg[u]:
                if v in done:
                    continue
                vv.append(v)
                s.append(v)
                done.add(v)
        ans.append(vv)


    return ans


def atcoder_practice2_g():
    N, M = map(int, input().split())

    E = []
    for _ in range(M):
        a, b = map(int, input().split())
        E.append((a, b))
    V = list(range(N))
    vv = scc(V, E)
    print(len(vv))
    for r in vv:
        print(len(r), *r)


def test():
    g = {
        1: [2],
        5: [2],
        2: [4, 3],
        3: [4, 7, 6],
        4: [5, 8],
        6: [9],
        7: [8],
        8: [9],
        9: [7, 10],
        10: []
    }

    V = list(range(1, 11))
    E = []
    for u, e in g.items():
        for v in e:
            E.append((u, v))

    vv = scc(V, E)
    for r in vv:
        print(r)


if __name__ == "__main__":
    # test()
    atcoder_practice2_g()

Submission status: Accepted

Solution code:

from collections import defaultdict
import sys

input = sys.stdin.buffer.readline

def scc(V, E):
    # g = defaultdict(list)
    g = [list() for _ in range(len(V))]
    # rg = defaultdict(list)
    rg = [list() for _ in range(len(V))]
    for u, v in E:
        g[u].append(v)
        rg[v].append(u)


    o = []
    done = set()
    for u in V:
        if u in done:
            continue

        s = [(u, True)]
        while s:
            u, f = s.pop()
            if f:
                if u in done:
                    continue
                done.add(u)
                s.append((u, False))
                for v in g[u]:
                    if v in done:
                        continue
                    s.append((v, True))
            else:
                o.append(u)

    done = set()
    ans = []
    while o:
        u = o.pop()
        if u in done:
            continue

        s = [u]
        vv = [u]
        done.add(u)
        while s:
            u = s.pop()
            for v in rg[u]:
                if v in done:
                    continue
                vv.append(v)
                s.append(v)
                done.add(v)
        ans.append(vv)


    return ans


def atcoder_practice2_g():
    N, M = map(int, input().split())

    E = []
    for _ in range(M):
        a, b = map(int, input().split())
        E.append((a, b))
    V = list(range(N))
    vv = scc(V, E)
    print(len(vv))
    for r in vv:
        print(len(r), *r)


def test():
    g = {
        1: [2],
        5: [2],
        2: [4, 3],
        3: [4, 7, 6],
        4: [5, 8],
        6: [9],
        7: [8],
        8: [9],
        9: [7, 10],
        10: []
    }

    V = list(range(1, 11))
    E = []
    for u, e in g.items():
        for v in e:
            E.append((u, v))

    vv = scc(V, E)
    for r in vv:
        print(r)


if __name__ == "__main__":
    # test()
    atcoder_practice2_g()

Submission status: Accepted

Solution code:

from collections import defaultdict
import sys

input = sys.stdin.buffer.readline

def scc(V, E):
    g = defaultdict(list)
    rg = defaultdict(list)
    for u, v in E:
        g[u].append(v)
        rg[v].append(u)


    o = []
    done = set()
    for u in V:
        if u in done:
            continue

        s = [(u, True)]
        while s:
            u, f = s.pop()
            if f:
                if u in done:
                    continue
                done.add(u)
                s.append((u, False))
                for v in g[u]:
                    if v in done:
                        continue
                    s.append((v, True))
            else:
                o.append(u)

    done = set()
    ans = []
    while o:
        u = o.pop()
        if u in done:
            continue

        s = [u]
        vv = [u]
        done.add(u)
        while s:
            u = s.pop()
            for v in rg[u]:
                if v in done:
                    continue
                vv.append(v)
                s.append(v)
                done.add(v)
        ans.append(vv)


    return ans


def atcoder_practice2_g():
    N, M = map(int, input().split())

    E = []
    for _ in range(M):
        a, b = map(int, input().split())
        E.append((a, b))
    V = list(range(N))
    vv = scc(V, E)
    print(len(vv))
    for r in vv:
        print(len(r), *r)


def test():
    g = {
        1: [2],
        5: [2],
        2: [4, 3],
        3: [4, 7, 6],
        4: [5, 8],
        6: [9],
        7: [8],
        8: [9],
        9: [7, 10],
        10: []
    }

    V = list(range(1, 11))
    E = []
    for u, e in g.items():
        for v in e:
            E.append((u, v))

    vv = scc(V, E)
    for r in vv:
        print(r)


if __name__ == "__main__":
    # test()
    atcoder_practice2_g()

Submission status: Accepted

Solution code:

from collections import defaultdict
import sys
sys.setrecursionlimit(10**6)

def scc(V, E):
    g = defaultdict(list)
    rg = defaultdict(list)
    for u, v in E:
        g[u].append(v)
        rg[v].append(u)


    o = []
    done = set()
    for u in V:
        if u in done:
            continue

        s = [(u, True)]
        while s:
            u, f = s.pop()
            if f:
                if u in done:
                    continue
                done.add(u)
                s.append((u, False))
                for v in g[u]:
                    if v in done:
                        continue
                    s.append((v, True))
            else:
                o.append(u)

    done = set()
    ans = []
    while o:
        u = o.pop()
        if u in done:
            continue

        s = [u]
        vv = [u]
        done.add(u)
        while s:
            u = s.pop()
            for v in rg[u]:
                if v in done:
                    continue
                vv.append(v)
                s.append(v)
                done.add(v)
        ans.append(vv)


    return ans


def atcoder_practice2_g():
    N, M = map(int, input().split())

    E = []
    for _ in range(M):
        a, b = map(int, input().split())
        E.append((a, b))
    V = list(range(N))
    vv = scc(V, E)
    print(len(vv))
    for r in vv:
        print(len(r), *r)


def test():
    g = {
        1: [2],
        5: [2],
        2: [4, 3],
        3: [4, 7, 6],
        4: [5, 8],
        6: [9],
        7: [8],
        8: [9],
        9: [7, 10],
        10: []
    }

    V = list(range(1, 11))
    E = []
    for u, e in g.items():
        for v in e:
            E.append((u, v))

    vv = scc(V, E)
    for r in vv:
        print(r)


if __name__ == "__main__":
    # test()
    atcoder_practice2_g()

Submission status: Accepted

Solution code:

from collections import defaultdict
import sys
sys.setrecursionlimit(10**6)

def scc(V, E):
    g = defaultdict(list)
    rg = defaultdict(list)
    for u, v in E:
        g[u].append(v)
        rg[v].append(u)


    o = []
    visited = set()
    used = set()
    for u in V:
        if u in visited:
            continue

        s = [(u, True)]
        while s:
            u, f = s.pop()
            if f:
                if u in visited:
                    continue
                visited.add(u)
                s.append((u, False))
                for v in g[u]:
                    if v in visited:
                        continue
                    s.append((v, True))
            else:
                o.append(u)



    def dfs(u, done, o):
        done.add(u)
        for v in g[u]:
            if v in done:
                continue
            done.add(v)
            dfs(v, done, o)
        o.append(u)

    def dfs_rev(u, done, c):
        done.add(u)
        c.append(u)
        for v in rg[u]:
            if v in done:
                continue
            dfs_rev(v, done, c)

    # done = set()
    # oo = []
    # for v in V:
    #     if v in done:
    #         continue
    #     dfs(v, done, oo)

    # print('---')
    # print(o)
    # print(oo)


    done = set()
    ans = []
    while o:
        u = o.pop()
        if u in done:
            continue
        vv = []
        dfs_rev(u, done, vv)
        ans.append(vv)


    return ans


def atcoder_practice2_g():
    N, M = map(int, input().split())

    E = []
    for _ in range(M):
        a, b = map(int, input().split())
        E.append((a, b))
    V = list(range(N))
    vv = scc(V, E)
    print(len(vv))
    for r in vv:
        print(len(r), *r)


def test():
    g = {
        1: [2],
        5: [2],
        2: [4, 3],
        3: [4, 7, 6],
        4: [5, 8],
        6: [9],
        7: [8],
        8: [9],
        9: [7, 10],
        10: []
    }

    V = list(range(1, 11))
    E = []
    for u, e in g.items():
        for v in e:
            E.append((u, v))

    vv = scc(V, E)
    for r in vv:
        print(r)


if __name__ == "__main__":
    # test()
    atcoder_practice2_g()

Submission status: Accepted

Solution code:

from collections import defaultdict
import sys
sys.setrecursionlimit(10**6)

def scc(V, E):
    g = defaultdict(list)
    rg = defaultdict(list)
    for u, v in E:
        g[u].append(v)
        rg[v].append(u)

    def dfs(u, done, o):
        done.add(u)
        for v in g[u]:
            if v in done:
                continue
            done.add(v)
            dfs(v, done, o)
        o.append(u)

    def dfs_rev(u, done, c):
        done.add(u)
        c.append(u)
        for v in rg[u]:
            if v in done:
                continue
            dfs_rev(v, done, c)

    done = set()
    o = []
    for v in V:
        if v in done:
            continue
        dfs(v, done, o)


    done = set()
    ans = []
    while o:
        u = o.pop()
        if u in done:
            continue
        vv = []
        dfs_rev(u, done, vv)
        ans.append(vv)


    return ans


def atcoder_practice2_g():
    N, M = map(int, input().split())

    E = []
    for _ in range(M):
        a, b = map(int, input().split())
        E.append((a, b))
    V = list(range(N))
    vv = scc(V, E)
    print(len(vv))
    for r in vv:
        print(len(r), *r)


def test():
    g = {
        1: [2],
        5: [2],
        2: [4, 3],
        3: [4, 7, 6],
        4: [5, 8],
        6: [9],
        7: [8],
        8: [9],
        9: [7, 10],
        10: []
    }

    vv = scc(g)
    for r in vv:
        print(r)


if __name__ == "__main__":
    # test()
    atcoder_practice2_g()

Submission status: Accepted

Solution code:

from collections import defaultdict
import sys
sys.setrecursionlimit(10**6)

def scc(N, g, rg):
    V = list(range(N))


    def dfs(u, done, o):
        done.add(u)
        for v in g[u]:
            if v in done:
                continue
            done.add(v)
            dfs(v, done, o)
        o.append(u)

    def dfs_rev(u, done, c):
        done.add(u)
        c.append(u)
        for v in rg[u]:
            if v in done:
                continue
            dfs_rev(v, done, c)

    done = set()
    o = []
    for v in V:
        if v in done:
            continue
        dfs(v, done, o)


    done = set()
    ans = []
    while o:
        u = o.pop()
        if u in done:
            continue
        vv = []
        dfs_rev(u, done, vv)
        ans.append(vv)


    return ans


def atcoder_practice2_g():
    N, M = map(int, input().split())

    g = defaultdict(list)
    rg = defaultdict(list)
    for _ in range(M):
        a, b = map(int, input().split())
        g[a].append(b)
        rg[b].append(a)
    vv = scc(N, g, rg)
    print(len(vv))
    for r in vv:
        print(len(r), *r)


def test():
    g = {
        1: [2],
        5: [2],
        2: [4, 3],
        3: [4, 7, 6],
        4: [5, 8],
        6: [9],
        7: [8],
        8: [9],
        9: [7, 10],
        10: []
    }

    vv = scc(g)
    for r in vv:
        print(r)


if __name__ == "__main__":
    # test()
    atcoder_practice2_g()

Submission status: Accepted

Solution code:
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**7)

N,M=map(int,input().split())
E=[[] for i in range(N)]
E_INV=[[] for i in range(N)]

for i in range(M):
    x,y=map(int,input().split())
    E[x].append(y)
    E_INV[y].append(x)

QUE = list(range(N))
check=[0]*N
TOP_SORT=[]

def dfs(x):
    if check[x]==1:
        return
    check[x]=1
    
    for to in E[x]:
        if check[to]==0:
            dfs(to)

    TOP_SORT.append(x) # 全ての点からDFSを行い, 帰りがけに点を答えに入れる
    check[x]=1

while QUE:
    x=QUE.pop()
    dfs(x)

USE=[0]*N
SCC=[]

def dfs2(x):
    Q=[x]
    USE[x]=1
    ANS=[]

    while Q:
        x=Q.pop()
        ANS.append(x)
        for to in E_INV[x]:
            if USE[to]==0:
                USE[to]=1
                Q.append(to)
    return ANS

for x in TOP_SORT[::-1]:
    if USE[x]==0:
        SCC.append(dfs2(x))

print(len(SCC))
for x in SCC:
    print(len(x),*x)

Submission status: Accepted

Solution code:
def SCC_Tarjan(g):
    n = len(g)
    order = [-1]*n # 負なら未処理、[0,n) ならpre-order, n ならvisited
    low = [0]*n
    ord_now = 0
    parent = [-1]*n
    gp = [0]*n
    gp_num = 0
    S = []
    q = []
    for i in range(n):
        if order[i] == -1:
            q.append(i)
            while q:
                v = q.pop()
                if v >= 0:
                    if order[v] != -1: continue
                    order[v] = low[v] = ord_now
                    ord_now += 1
                    S.append(v)
                    q.append(~v)
                    for c in g[v]:
                        if order[c] == -1: 
                            q.append(c)
                            parent[c] = v
                        else:
                            low[v] = min(low[v], order[c])
                else:
                    v = ~v
                    if parent[v] != -1:
                        low[parent[v]] = min(low[parent[v]], low[v])
                    if low[v] == order[v]:
                        while True:
                            w = S.pop()
                            order[w] = n
                            gp[w] = gp_num
                            if w==v: break
                        gp_num += 1


    scc = [[] for _ in range(gp_num)]
    for i in range(n):
        gp[i] = gp_num-gp[i]-1
        scc[gp[i]].append(i)
    
    #print(gp)
    return scc

###########################################################################                        
###########################################################################                        

# coding: utf-8
# Your code here!
import sys
readline = sys.stdin.readline
read = sys.stdin.read

n,m = [int(i) for i in readline().split()]

g = [[] for _ in range(n)]
for _ in range(m):
    a,b = map(int, readline().split())
    g[a].append(b)

scc = SCC_Tarjan(g)
print(len(scc))
for lst in scc:
    print(*([len(lst)]+lst))

Submission status: Accepted

Solution code:
def SCC_Tarjan(g):
    def dfs(v):
        nonlocal idx
        pre[v] = low[v] = idx
        idx += 1
        S.append(v)
        #onS[v] = 1
        for c in g[v]:
            if pre[c] == -1: 
                dfs(c)
                low[v] = min(low[v], low[c])
            #elif onS[c]:
            else:
                low[v] = min(low[v], pre[c])

        if low[v] == pre[v]:
            cc = []
            while True:
                w = S.pop()
                #onS[w] = 0
                pre[w] = n
                cc.append(w)
                if w==v: break
            scc.append(cc)


    n = len(g)
    pre = [-1]*n # 負なら未処理、[0,n) ならpre-order, n ならvisited
    low = [0]*n
    onS = [0]*n
    idx = 0
    S = []
    scc = []
    for i in range(n):
        if pre[i] == -1:
            dfs(i)
    
    #print(g)    
    #print("idx",pre)
    #print("low",low)
    #print(scc)
        
    return scc

###########################################################################                        
###########################################################################                        

# coding: utf-8
# Your code here!
import sys
readline = sys.stdin.readline
read = sys.stdin.read
sys.setrecursionlimit(10**6)
#n,*w = [int(i) for i in read().split()]

n,m = [int(i) for i in readline().split()]

g = [[] for _ in range(n)]
for _ in range(m):
    a,b = map(int, readline().split())
    g[a].append(b)

gp = SCC_Tarjan(g)
print(len(gp))
for lst in gp[::-1]:
    print(*([len(lst)]+lst))

Submission status: Accepted

Solution code:
def SCC_Tarjan(g):
    def dfs(v):
        nonlocal idx
        used[v] = 1
        pre[v] = low[v] = idx
        idx += 1
        S.append(v)
        onS[v] = 1
        for c in g[v]:
            if not used[c]:
                dfs(c)
                low[v] = min(low[v], low[c])
            elif onS[c]:
                low[v] = min(low[v], pre[c])
        used[v] = 2

        if low[v] == pre[v]:
            cc = []
            while True:
                w = S.pop()
                onS[w] = 0
                cc.append(w)
                if w==v: break
            scc.append(cc)


    n = len(g)
    used = [0]*n # 0 -> 1 -> 2
    pre = [0]*n
    low = [0]*n
    onS = [0]*n
    idx = 0
    S = []
    scc = []
    for i in range(n):
        if not used[i]:
            dfs(i)
    #print(g)    
    #print("idx",pre)
    #print("low",low)
    #print(scc)
        
    return scc

###########################################################################                        
###########################################################################                        

# coding: utf-8
# Your code here!
import sys
readline = sys.stdin.readline
read = sys.stdin.read
sys.setrecursionlimit(10**6)
#n,*w = [int(i) for i in read().split()]

n,m = [int(i) for i in readline().split()]

g = [[] for _ in range(n)]
for _ in range(m):
    a,b = map(int, readline().split())
    g[a].append(b)

gp = SCC_Tarjan(g)
print(len(gp))
for lst in gp[::-1]:
    print(*([len(lst)]+lst))