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

Solution (Python):
def StrongConnectedComponent(g,S):
    from collections import deque
    S = deque() 
    
    q = deque()
    n = len(g)
    gp = [1]*n 
    for i in range(n):
        if gp[i] == 1:
            q.append(i)
            while q:
                v = q.pop()
                
                if v < 0:
                    if gp[~v] == 0:
                        gp[~v] = -1
                        S.append(~v)
                
                elif gp[v] == 1:
                    q.append(~v)
                    gp[v] = 0
                    for c in rg[v]:
                        
                        if gp[c] == 1:
                            q.append(c)
    q = deque()
    gp = [-1]*n
    
    
    g_scc = []
    cnt = 0
    while S:
        v = S.pop()
        if gp[v] == -1:
            q.append(v)
            gp[v] = cnt
            sv = set()
            while q:
                w = q.pop()
                for c in g[w]:
                    if gp[c] == -1:
                        q.append(c)
                        gp[c] = gp[w]
                    elif gp[c] != cnt:
                        sv.add(gp[c])
            cnt += 1
            g_scc.append(sv)

    return gp, g_scc






import sys
readline = sys.stdin.readline
read = sys.stdin.read



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

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



gp, scc = StrongConnectedComponent(g,rg)





v = max(gp)+1
ans = [[] for _ in range(v)]
for i, gpi in enumerate(gp):
    ans[gpi].append(i)

print(v)
for lst in ans[::-1]:
    print(len(lst), end=" ")
    print(*lst)

Solution (Python):

code = """






from libc.stdio cimport getchar, printf
from libcpp.vector cimport vector
from libcpp.string cimport string
cpdef inline vector[int] ReadInt(int n):
    cdef int b, c
    cdef vector[int] *v = new vector[int]()
    for i in range(n):
        c = 0
        while 1:
            b = getchar() - 48
            if b < 0: break
            c = c * 10 + b
        v.push_back(c)
    return v[0]

cpdef inline vector[string] Read(int n):
    cdef char c
    cdef vector[string] *vs = new vector[string]()
    cdef string *s
    for i in range(n):
        s = new string()
        while 1:
            c = getchar()
            if c<=32: break
            s.push_back(c)
        vs.push_back(s[0])
    return vs[0]

cpdef inline void PrintLongN(vector[long] l, int n):
    for i in range(n): printf("%ld\\n", l[i])

cpdef inline void PrintLong(vector[long] l, int n):
    for i in range(n): printf("%ld ", l[i])
cdef extern from "<atcoder/scc>" namespace "atcoder":
    cdef cppclass scc_graph:
        scc_graph(int n)
        void add_edge(int fr, int to)
        vector[vector[int]] scc()

cdef class SccGraph:
    cdef scc_graph *_thisptr
    def __cinit__(self, int n):
        self._thisptr = new scc_graph(n)
    cpdef void add_edge(self, int fr, int to):
        self._thisptr.add_edge(fr, to)
    cpdef vector[vector[int]] scc(self):
        return self._thisptr.scc()
"""


import os, sys, getpass

if sys.argv[-1] == 'ONLINE_JUDGE':
    code.replace("USERNAME", getpass.getuser())
    open('atcoder.pyx','w').write(code)
    os.system('cythonize -i -3 -b atcoder.pyx')
    sys.exit(0)


from atcoder import SccGraph, ReadInt

def main():
    N, M = ReadInt(2)
    sg = SccGraph(N)
    for i in range(M):
        a, b = ReadInt(2)
        sg.add_edge(a, b)
    ans = sg.scc()
    print(len(ans))
    for i in range(len(ans)):
        print(len(ans[i]),*ans[i])

if __name__=="__main__":
    main()

Solution (Python):
class csr():
    def __init__(self, n: int, edges: list):
        self.start = [0] * (n+1)
        self.elist = [0] * len(edges)
        for e in edges:
            self.start[e[0]+1] += 1
        for i in range(1, n+1):
            self.start[i] += self.start[i-1]
        counter = self.start[::]
        for e in edges:
            self.elist[counter[e[0]]] = e[1]
            counter[e[0]] += 1


class internal_scc_graph():
    def __init__(self, n: int = 0):
        self.__n = n
        self.__edges = []

    def num_vertices(self):
        return self.__n

    def add_edge(self, from_: int, to: int):
        self.__edges.append([from_, to])

    def scc_ids(self):
        g = csr(self.__n, self.__edges)
        now_ord = 0
        group_num = 0
        visited = []
        low = [0] * self.__n
        ord = [-1] * self.__n
        ids = [0] * self.__n
        parent = [-1] * self.__n

        for root in range(self.__n):
            if(ord[root] == -1):
                stack = []
                stack.extend([root]*2)
                while(stack):
                    v = stack.pop()
                    if(ord[v] == -1):
                        visited.append(v)
                        low[v] = now_ord
                        ord[v] = now_ord
                        now_ord += 1
                        for i in range(g.start[v], g.start[v+1]):
                            to = g.elist[i]
                            if(ord[to] == -1):
                                stack.extend([to]*2)
                                parent[to] = v
                            else:
                                low[v] = min(low[v], ord[to])
                    else:
                        if(low[v] == ord[v]):
                            while(True):
                                u = visited.pop()
                                ord[u] = self.__n
                                ids[u] = group_num
                                if(u == v):
                                    break
                            group_num += 1
                        if(parent[v] != -1):
                            low[parent[v]] = min(low[parent[v]], low[v])


        for i, x in enumerate(ids):
            ids[i] = group_num - 1 - x
        return [group_num, ids]

    def scc(self):
        ids = self.scc_ids()
        group_num = ids[0]
        counts = [0] * group_num
        for x in ids[1]:
            counts[x] += 1
        groups = [[] for _ in range(group_num)]
        for i, x in enumerate(ids[1]):
            groups[x].append(i)

        return groups


class scc_graph():
    def __init__(self, n: int):
        self.__internal = internal_scc_graph(n)

    def add_edge(self, from_: int, to: int):
        n = self.__internal.num_vertices()
        assert (0 <= from_) & (from_ < n)
        assert (0 <= to) & (to < n)
        self.__internal.add_edge(from_, to)

    def scc(self):
        return self.__internal.scc()

import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines

n,m = map(int,readline().split())
data = list(map(int,read().split()))

sg = scc_graph(n)
it = iter(data)
for a,b in zip(it,it):
    sg.add_edge(a,b)

scc = sg.scc()
print(len(scc))
ans = []
for group in scc:
    tmp = [len(group)] + group
    ans.append(' '.join(map(str,tmp)))
print('\n'.join(map(str,ans)))

Solution (Python):
code = r"""




from libcpp cimport bool
from libcpp.string cimport string
from libcpp.vector cimport vector

cdef extern from "<atcoder/dsu>" namespace "atcoder":
    cpdef cppclass dsu:
        dsu(int n)
        int merge(int a, int b)
        bool same(int a, int b)
        int leader(int a)
        int size(int a)
        vector[vector[int]] groups()
cdef class dsu_:
    cdef dsu *ptr
    def __cinit__(self, int n): self.ptr = new dsu(n)
    def __dealloc__(self): del self.ptr
    cpdef int merge(self,a,b): return self.ptr.merge(a,b)
    cpdef bool same(self,a,b): return self.ptr.same(a,b)
    cpdef int leader(self,a): return self.ptr.leader(a)
    cpdef int size(self,a): return self.ptr.size(a)
    cpdef vector[vector[int]] groups(self): return self.ptr.groups()

cdef extern from "<atcoder/fenwicktree>" namespace "atcoder":
    cdef cppclass fenwick_tree[T]:
        fenwick_tree(int n)
        void add(int p, T x)
        T sum(int l, int r)
cdef class fenwick_tree_:
    cdef fenwick_tree[int] *ptr
    def __cinit__(self, int n): self.ptr = new fenwick_tree[int](n)  
    def __dealloc__(self): del self.ptr
    cpdef void add(self, int p, long x): self.ptr.add(p, x)
    cpdef long sum(self, int l, int r): return self.ptr.sum(l, r)

cdef extern from "<atcoder/string>" namespace "atcoder":
    vector[int] suffix_array(vector[int] s, int upper)
    vector[int] suffix_array(vector[long] s)
    vector[int] suffix_array(string s)
    vector[int] lcp_array(vector[long] s, vector[int] sa)
    vector[int] lcp_array(string s, vector[int] sa)
    vector[int] z_algorithm(vector[long] s)
    vector[int] z_algorithm(string s)
cpdef vector[int] suffix_array_u(vector[int] s, int upper): return suffix_array(s, upper)
cpdef vector[int] suffix_array_l(vector[long] s): return suffix_array(s)
cpdef vector[int] suffix_array_s(string s): return suffix_array(s)
cpdef vector[int] lcp_array_l(vector[long] s, vector[int] sa): return lcp_array(s, sa)
cpdef vector[int] lcp_array_s(string s, vector[int] sa): return lcp_array(s, sa)
cpdef vector[int] z_algorithm_l(vector[long] s): return z_algorithm(s)
cpdef vector[int] z_algorithm_s(string s): return z_algorithm(s)

cdef extern from "<atcoder/maxflow>" namespace "atcoder":
    cdef cppclass mf_graph[Cap]:
        mf_graph(int n)
        int add_edge(int frm, int to, Cap cap)
        Cap flow(int s, int t)
        Cap flow(int s, int t, Cap flow_limit)
        vector[bool] min_cut(int s)
        cppclass edge:
            int frm "from", to
            Cap cap, flow
            edge(edge &e)
        edge get_edge(int i)
        vector[edge] edges()
        void change_edge(int i, Cap new_cap, Cap new_flow)
cdef class mf_graph_:
    cdef mf_graph[int] *ptr
    def __cinit__(self, int n): self.ptr = new mf_graph[int](n)  
    def __dealloc__(self): del self.ptr
    cpdef int add_edge(self, int frm, int to, int cap): return self.ptr.add_edge(frm, to, cap)
    cpdef int flow(self, int s, int t): return self.ptr.flow(s, t)
    cpdef int flow_limit(self, int s, int t, int flow_limit): return self.ptr.flow(s, t, flow_limit)
    cpdef vector[bool] min_cut(self, int s): return self.ptr.min_cut(s)
    cpdef vector[int] get_edge(self, int i):
        cdef mf_graph[int].edge *e = new mf_graph[int].edge(self.ptr.get_edge(i))
        cdef vector[int] *ret_e = new vector[int]()        
        ret_e.push_back(e.frm)
        ret_e.push_back(e.to)
        ret_e.push_back(e.cap)
        ret_e.push_back(e.flow)
        return ret_e[0]
    cpdef vector[vector[int]] edges(self):
        cdef vector[mf_graph[int].edge] es = self.ptr.edges()
        cdef vector[vector[int]] *ret_es = new vector[vector[int]](es.size())
        for i in range(es.size()):
            ret_es.at(i).push_back(es.at(i).frm)
            ret_es.at(i).push_back(es.at(i).to)
            ret_es.at(i).push_back(es.at(i).cap)
            ret_es.at(i).push_back(es.at(i).flow)
        return ret_es[0]
    cpdef void change_edge(self, int i, int new_cap, int new_flow): self.ptr.change_edge(i, new_cap, new_flow)

cdef extern from *:
    ctypedef int MOD "998244353"
    ctypedef long long ll "long long"
cdef extern from "<atcoder/convolution>" namespace "atcoder":
    vector[int] convolution[m](vector[int] a, vector[int] b)
    vector[ll] convolution_ll(vector[ll] a, vector[ll] b)
cpdef vector[int] convolution_(vector[int] a, vector[int] b): return convolution[MOD](a, b)
cpdef vector[ll] convolution_ll_(vector[ll] a, vector[ll] b): return convolution_ll(a, b)

cdef extern from "<atcoder/scc>" namespace "atcoder":
    cdef cppclass scc_graph:
        scc_graph(int n)
        void add_edge(int fr, int to)
        vector[vector[int]] scc()
cdef class scc_graph_:
    cdef scc_graph *ptr
    def __cinit__(self, int n): self.ptr = new scc_graph(n)  
    def __dealloc__(self): del self.ptr
    cpdef void add_edge(self, int fr, int to): self.ptr.add_edge(fr, to)
    cpdef vector[vector[int]] scc(self): return self.ptr.scc()
"""

import os
try:
    from atcoder import *
except:
    open('atcoder.pyx', 'w').write(code)
    os.system('cythonize -i -3 -b atcoder.pyx')

N,M=map(int,input().split())
AB=[list(map(int,input().split())) for i in range(M)]
g=scc_graph_(N)
for a,b in AB:
    g.add_edge(a,b)
r=g.scc()
print(len(r))
for l in r:
    print(len(l),*l)

Solution (Python):
from collections import deque

class StronglyConnectedComponents():
    def __init__(self, n):
        self.n = n
        self.graph = [[] for _ in range(n)]
        self.rev = [[] for _ in range(n)]

    def add_edge(self, fr, to):
        self.graph[fr].append(to)
        self.rev[to].append(fr)

    def scc_id(self):
        group = [0] * self.n
        order = []
        for s in range(self.n):
            if group[s]: continue
            stack = deque([s])
            group[s] = -1
            while stack:
                node = stack.pop()
                for adj in self.graph[node]:
                    if group[adj]: continue
                    group[adj] = -1
                    stack.append(node)
                    stack.append(adj)
                    break
                else:
                    order.append(node)
        cnt = 0
        for s in order[::-1]:
            if group[s] != -1: continue
            stack = deque([s])
            group[s] = cnt
            while stack:
                node = stack.pop()
                for adj in self.rev[node]:
                    if group[adj] != -1: continue
                    group[adj] = cnt
                    stack.append(adj)
            cnt += 1
        return group, cnt

    def scc(self):
        group, cnt = self.scc_id()
        res = [[] for _ in range(cnt)]
        for i, g in enumerate(group):
            res[g].append(i)
        return res

import sys
input = sys.stdin.buffer.readline

N, M = map(int, input().split())

scc = StronglyConnectedComponents(N)

for _ in range(M):
    a, b = map(int, input().split())
    scc.add_edge(a, b)

res = scc.scc()
print(len(res))

for r in res:
    print(len(r), *r)

Solution (Python):
class DiGraph:
    def __init__(self, n):
        self.n = n
        self.graph = [[] for _ in range(n)]
        self.rev = [[] for _ in range(n)]
        self.deg = [0 for _ in range(n)]

    def add_edge(self, fr, to):
        self.graph[fr].append(to)
        self.rev[to].append(fr)
        self.deg[to] += 1

    def scc_ids(self):
        group = [None for _ in range(self.n)]
        used = [0 for _ in range(self.n)]
        order = []
        for s in range(self.n):
            if not used[s]:
                stack = [s]
                used[s] = 1
                while stack:
                    node = stack.pop()
                    movable = False
                    for adj in self.graph[node]:
                        if not used[adj]:
                            movable = True
                            used[adj] = 1
                            stack.append(node)
                            stack.append(adj)
                            break
                    if not movable:
                        order.append(node)
        used = [0 for _ in range(self.n)]
        count = 0
        for s in order[::-1]:
            if not used[s]:
                stack = [s]
                group[s] = count
                while stack:
                    node = stack.pop()
                    used[node] = 1
                    for adj in self.rev[node]:
                        if not used[adj]:
                            group[adj] = count
                            stack.append(adj)
                count += 1
        return group, count

    def scc(self):
        group, count = self.scc_ids()

        scc = [[] for _ in range(count)]
        for i, k in enumerate(group):
            scc[k].append(i)

        return scc


N, M = map(int, input().split())

dg = DiGraph(N)

for i in range(M):
    dg.add_edge(*list(map(int, input().split())))

scc = dg.scc()

print(len(scc))
for c in scc:
    print(len(c), ' '.join(map(str, c)))

Solution (Python):

import sys
sys.setrecursionlimit(1000000)

class scc_graph:
  
  def __init__(s, n): 
    s._n = n
    s.g = {}
  def num_vertices(s): return s._n
  
  
  def add_edge(s, frm, to): 
    if frm in s.g: s.g[frm].append(to)
    else: s.g[frm] = [to]

  
  def scc_ids(s):
    now_ord = group_num = 0
    visited = []
    low = [0] * s._n
    ord = [-1] * s._n
    ids = [0] * s._n
    
    def dfs(self, v, now_ord, group_num):
      low[v] = ord[v] = now_ord
      now_ord += 1
      visited.append(v)
      if v in s.g:
        for to in s.g[v]:
          if ord[to] == -1:
            now_ord, group_num = self(self, to, now_ord, group_num)
            low[v] = min(low[v], low[to])
          else:
            low[v] = min(low[v], ord[to])
      if low[v] == ord[v]:
        while True:
          u = visited.pop()
          ord[u] = s._n
          ids[u] = group_num
          if u == v: break
        group_num += 1
      return now_ord, group_num

    for i in range(s._n):
      if ord[i] == -1: now_ord, group_num = dfs(dfs, i, now_ord, group_num)
    for i in range(s._n):
      ids[i] = group_num - 1 - ids[i]
    return group_num, ids

  
  
  def scc(s):
    group_num, ids = s.scc_ids()
    counts = [0] * group_num
    for x in ids: counts[x] += 1
    groups = [[] for _ in range(group_num)]
    for i in range(s._n):
      groups[ids[i]].append(i)
    return groups

  class edge:
    def __init__(s, frm, to):
      s.frm = frm
      s.to = to




def main():
  input = sys.stdin.readline
  n, m = list(map(int, input().split()))
  ab = [tuple(map(int, input().split())) for _ in range(m)]

  g = scc_graph(n)

  for u, v in ab:
    g.add_edge(u, v)

  scc = g.scc()

  print(len(scc))

  for v in scc:
    print(len(v), end = " ")
    for x in v:
      print(x, end = " ")
    print("")

main()

Solution (Python):

import sys
sys.setrecursionlimit(1000000)

class scc_graph:
  
  def __init__(s, n): 
    s._n = n
    s.g = {}
  def num_vertices(s): return s._n
  
  
  def add_edge(s, frm, to): 
    if frm in s.g: s.g[frm].append(to)
    else: s.g[frm] = [to]

  
  def scc_ids(s):
    now_ord = group_num = 0
    visited = []
    low = [0] * s._n
    ord = [-1] * s._n
    ids = [0] * s._n
    
    def dfs(self, v, now_ord, group_num):
      low[v] = ord[v] = now_ord
      now_ord += 1
      visited.append(v)
      if v in s.g:
        for to in s.g[v]:
          if ord[to] == -1:
            now_ord, group_num = self(self, to, now_ord, group_num)
            low[v] = min(low[v], low[to])
          else:
            low[v] = min(low[v], ord[to])
      if low[v] == ord[v]:
        while True:
          u = visited.pop()
          ord[u] = s._n
          ids[u] = group_num
          if u == v: break
        group_num += 1
      return now_ord, group_num

    for i in range(s._n):
      if ord[i] == -1: now_ord, group_num = dfs(dfs, i, now_ord, group_num)
    for i in range(s._n):
      ids[i] = group_num - 1 - ids[i]
    return group_num, ids

  
  
  def scc(s):
    ids = s.scc_ids()
    group_num = ids[0]
    counts = [0] * group_num
    for x in ids[1]: counts[x] += 1
    groups = [[] for _ in range(group_num)]
    for i in range(s._n):
      groups[ids[1][i]].append(i)
    return groups

  class edge:
    def __init__(s, frm, to):
      s.frm = frm
      s.to = to




input = sys.stdin.readline

n, m = list(map(int, input().split()))
ab = [list(map(int, input().split())) for _ in range(m)]

g = scc_graph(n)

for i in range(m):
  u, v = ab[i]
  g.add_edge(u, v)

scc = g.scc()

print(len(scc))

for v in scc:
  print(len(v), end = " ")
  for x in v:
    print(x, end = " ")
  print("")

Solution (Python):

import sys
sys.setrecursionlimit(1000000)

class scc_graph:
  
  def __init__(s, n): 
    s._n = n
    s.g = {}
  def num_vertices(s): return s._n
  
  
  def add_edge(s, frm, to): 
    if frm in s.g: s.g[frm].append(to)
    else: s.g[frm] = [to]

  
  def scc_ids(s):
    now_ord = group_num = 0
    visited = []
    low = [0] * s._n
    ord = [-1] * s._n
    ids = [0] * s._n
    
    def dfs(self, v, now_ord, group_num):
      low[v] = ord[v] = now_ord
      now_ord += 1
      visited.append(v)
      if v in s.g:
        for to in s.g[v]:
          if ord[to] == -1:
            now_ord, group_num = self(self, to, now_ord, group_num)
            low[v] = min(low[v], low[to])
          else:
            low[v] = min(low[v], ord[to])
      if low[v] == ord[v]:
        while True:
          u = visited.pop()
          ord[u] = s._n
          ids[u] = group_num
          if u == v: break
        group_num += 1
      return now_ord, group_num

    for i in range(s._n):
      if ord[i] == -1: now_ord, group_num = dfs(dfs, i, now_ord, group_num)
    for i in range(s._n):
      ids[i] = group_num - 1 - ids[i]
    return [group_num, ids]

  
  
  def scc(s):
    ids = s.scc_ids()
    group_num = ids[0]
    counts = [0] * group_num
    for x in ids[1]: counts[x] += 1
    groups = [[] for _ in range(group_num)]
    for i in range(s._n):
      groups[ids[1][i]].append(i)
    return groups

  class edge:
    def __init__(s, frm, to):
      s.frm = frm
      s.to = to




def main():
  input = sys.stdin.readline

  n, m = list(map(int, input().split()))
  ab = [list(map(int, input().split())) for _ in range(m)]

  g = scc_graph(n)

  for i in range(m):
    u, v = ab[i]
    g.add_edge(u, v)

  scc = g.scc()

  print(len(scc))

  for v in scc:
    print(len(v), end = " ")
    for x in v:
      print(x, end = " ")
    print("")

main()

Solution (Python):

class scc_graph:
  
  def __init__(s, n): 
    s._n = n
    s.g = {}
    s.rg = {}
  def num_vertices(s): return s._n
  
  
  def add_edge(s, frm, to): 
    if frm in s.g: s.g[frm].append(to)
    else: s.g[frm] = [to]
    if to in s.rg: s.rg[to].append(frm)
    else: s.rg[to] = [frm]

  
  def scc_ids(s):
    def dfs(v):
      stack = [v]
      while stack:
        t = stack[-1]
        vis[t] = True
        if t not in s.g:
          vs.append(stack.pop())
          continue
        for i in s.g[t]:
          if not vis[i]:
            stack.append(i)
            break
        else:
          vs.append(stack.pop())

    def rdfs(v, n):
      stack = [v]
      vis[v] = True
      ids[v] = n
      while stack:
        t = stack.pop()
        vis[t] = True
        if t not in s.rg: continue
        for i in s.rg[t]:
          if not vis[i]:
            ids[i] = n
            stack.append(i)

    vis = [False] * s._n 
    vs = []
    ids = [-1] * s._n
    for i in range(s._n):
      if not vis[i]:
        dfs(i)
    group_num = 0
    vis = [False] * s._n 
    for i in vs[::-1]:
      if not vis[i]:
        rdfs(i, group_num)
        group_num += 1
    return group_num, ids 

  
  
  def scc(s):
    ids = s.scc_ids()
    group_num = ids[0]
    counts = [0] * group_num
    for x in ids[1]: counts[x] += 1
    groups = [[] for _ in range(group_num)]
    for i in range(s._n):
      groups[ids[1][i]].append(i)
    return groups



import sys
def main():
  input = sys.stdin.readline

  n, m = list(map(int, input().split()))
  ab = [list(map(int, input().split())) for _ in range(m)]

  g = scc_graph(n)

  for i in range(m):
    u, v = ab[i]
    g.add_edge(u, v)

  scc = g.scc()

  print(len(scc))

  for v in scc:
    print(len(v), end = " ")
    for x in v:
      print(x, end = " ")
    print("")

main()

Solution (Python):

class scc_graph:
  
  def __init__(s, n): 
    s._n = n
    s.edge = [s.component() for i in range(n)]
  def num_vertices(s): return s._n
  
  
  def add_edge(s, frm, to): 
    s.edge[frm].add_go(to)
    s.edge[to].add_rgo(frm)

  
  def scc_ids(s):
    def dfs(v):
      stack = [v]
      while stack:
        t = stack.pop()
        vis[t] = True
        for i in s.edge[t].go:
          if not vis[i]:
            stack.append(t)
            stack.append(i)
            break
        else:
          vs.append(t)

    def rdfs(v, n):
      stack = [v]
      vis[v] = True
      ids[v] = n
      while stack:
        t = stack.pop()
        vis[t] = True
        for i in s.edge[t].rgo:
          if not vis[i]:
            ids[i] = n
            stack.append(i)

    vis = [False] * s._n 
    vs = []
    ids = [-1] * s._n
    for i in range(s._n):
      if not vis[i]:
        dfs(i)
    group_num = 0
    vis = [False] * s._n 
    for i in vs[::-1]:
      if not vis[i]:
        rdfs(i, group_num)
        group_num += 1
    return group_num, ids 

  
  
  def scc(s):
    ids = s.scc_ids()
    group_num = ids[0]
    counts = [0] * group_num
    for x in ids[1]: counts[x] += 1
    groups = [[] for _ in range(group_num)]
    for i in range(s._n):
      groups[ids[1][i]].append(i)
    return groups

  class component:
    def __init__(s):
      s.go = []
      s.rgo = []
    def add_go(s, to):
      s.go.append(to)
    def add_rgo(s, frm):
      s.rgo.append(frm)



import sys
def main():
  input = sys.stdin.readline

  n, m = list(map(int, input().split()))
  ab = [list(map(int, input().split())) for _ in range(m)]

  g = scc_graph(n)

  for i in range(m):
    u, v = ab[i]
    g.add_edge(u, v)

  scc = g.scc()

  print(len(scc))

  for v in scc:
    print(len(v), end = " ")
    for x in v:
      print(x, end = " ")
    print("")

main()

Solution (Python):

class scc_graph:
  
  def __init__(s, n): 
    s._n = n
    s.g = {}
    s.rg = {}
  def num_vertices(s): return s._n
  
  
  def add_edge(s, frm, to): 
    if frm in s.g: s.g[frm].append(to)
    else: s.g[frm] = [to]
    if to in s.rg: s.rg[to].append(frm)
    else: s.rg[to] = [frm]

  
  def scc_ids(s):
    def dfs(v):
      stack = [v]
      while stack:
        t = stack.pop()
        vis[t] = True
        if t not in s.g:
          vs.append(t)
          continue
        for i in s.g[t]:
          if not vis[i]:
            stack.append(t)
            stack.append(i)
            break
        else:
          vs.append(t)

    def rdfs(v, n):
      stack = [v]
      vis[v] = True
      ids[v] = n
      while stack:
        t = stack.pop()
        vis[t] = True
        if t not in s.rg: continue
        for i in s.rg[t]:
          if not vis[i]:
            ids[i] = n
            stack.append(i)

    vis = [False] * s._n 
    vs = []
    ids = [-1] * s._n
    for i in range(s._n):
      if not vis[i]:
        dfs(i)
    group_num = 0
    vis = [False] * s._n 
    for i in vs[::-1]:
      if not vis[i]:
        rdfs(i, group_num)
        group_num += 1
    return group_num, ids 

  
  
  def scc(s):
    ids = s.scc_ids()
    group_num = ids[0]
    counts = [0] * group_num
    for x in ids[1]: counts[x] += 1
    groups = [[] for _ in range(group_num)]
    for i in range(s._n):
      groups[ids[1][i]].append(i)
    return groups



import sys
def main():
  input = sys.stdin.readline

  n, m = list(map(int, input().split()))
  ab = [list(map(int, input().split())) for _ in range(m)]

  g = scc_graph(n)

  for i in range(m):
    u, v = ab[i]
    g.add_edge(u, v)

  scc = g.scc()

  print(len(scc))

  for v in scc:
    print(len(v), end = " ")
    for x in v:
      print(x, end = " ")
    print("")

main()

Solution (Python):

class scc_graph:
  
  def __init__(s, n): 
    s._n = n
    s.g = [[] for _ in range(n)]
    s.rg = [[] for _ in range(n)]
  def num_vertices(s): return s._n
  
  
  def add_edge(s, frm, to): 
    s.g[frm].append(to)
    s.rg[to].append(frm)

  
  def scc_ids(s):
    def dfs(v):
      stack = [v]
      while stack:
        t = stack.pop()
        vis[t] = True
        for i in s.g[t]:
          if not vis[i]:
            stack.append(t)
            stack.append(i)
            break
        else:
          vs.append(t)

    def rdfs(v, n):
      stack = [v]
      vis[v] = True
      ids[v] = n
      while stack:
        t = stack.pop()
        vis[t] = True
        for i in s.rg[t]:
          if not vis[i]:
            ids[i] = n
            stack.append(i)

    vis = [False] * s._n 
    vs = []
    ids = [-1] * s._n
    for i in range(s._n):
      if not vis[i]:
        dfs(i)
    group_num = 0
    vis = [False] * s._n 
    for i in vs[::-1]:
      if not vis[i]:
        rdfs(i, group_num)
        group_num += 1
    return group_num, ids 

  
  
  def scc(s):
    ids = s.scc_ids()
    group_num = ids[0]
    counts = [0] * group_num
    for x in ids[1]: counts[x] += 1
    groups = [[] for _ in range(group_num)]
    for i in range(s._n):
      groups[ids[1][i]].append(i)
    return groups



import sys
def main():
  input = sys.stdin.readline

  n, m = list(map(int, input().split()))
  ab = [list(map(int, input().split())) for _ in range(m)]

  g = scc_graph(n)

  for i in range(m):
    u, v = ab[i]
    g.add_edge(u, v)

  scc = g.scc()

  print(len(scc))

  for v in scc:
    print(len(v), end = " ")
    for x in v:
      print(x, end = " ")
    print("")

main()

Solution (Python):
class StronglyConnectedComponents():
    def __init__(self, n):
        self.n = n
        self.graph = [[] for _ in range(n)]
        self.rev = [[] for _ in range(n)]

    def add_edge(self, fr, to):
        self.graph[fr].append(to)
        self.rev[to].append(fr)

    def scc_id(self):
        group = [0] * self.n
        order = []
        for s in range(self.n):
            if group[s]: continue
            stack = [s]
            group[s] = -1
            while stack:
                node = stack.pop()
                for adj in self.graph[node]:
                    if group[adj]: continue
                    group[adj] = -1
                    stack.append(node)
                    stack.append(adj)
                    break
                else:
                    order.append(node)
        cnt = 0
        for s in order[::-1]:
            if group[s] != -1: continue
            stack = [s]
            group[s] = cnt
            while stack:
                node = stack.pop()
                for adj in self.rev[node]:
                    if group[adj] != -1: continue
                    group[adj] = cnt
                    stack.append(adj)
            cnt += 1
        return group, cnt

    def scc(self):
        group, cnt = self.scc_id()
        res = [[] for _ in range(cnt)]
        for i in range(self.n):
            res[group[i]].append(i)
        return res

import sys
input = sys.stdin.buffer.readline

N, M = map(int, input().split())

scc = StronglyConnectedComponents(N)

for _ in range(M):
    a, b = map(int, input().split())
    scc.add_edge(a, b)

res = scc.scc()
print(len(res))

for r in res:
    print(len(r), *r)