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

G1 = [[] for _ in range(N)]

G2 = [[] for _ in range(N)]

for i in range(M):

  a,b=list(map(int,input().split()))

  if a == b:continue

  G1[a].append(b)

  G2[b].append(a)



def dfs(a0):

    global order

    todo = [~a0, a0]

    while todo:

        a = todo.pop()

        if a >= 0:

            seen[a] = 1

            for b in G1[a]:

                if seen[b]: continue

                todo.append(~b)

                todo.append(b)

        else:

          if postorder[~a] == -1:

            postorder[~a] = order

            order += 1

    return

  

def dfs2(v):

    todo = [v]

    seen[v] = 1

    cc = [v]

    while todo:

        v = todo.pop()

        for next_v in G2[v]:

            if seen[next_v]: continue

            seen[next_v] = 1

            todo.append(next_v)

            cc.append(next_v)

    return cc

  

seen = [0]*N

postorder=[-1]*N

order = 0

for i in range(N):

  if seen[i]:continue

  dfs(i)



seen = [0]*N

scc = []

for i,_ in sorted(enumerate(postorder),key=lambda x:x[1],reverse=True):

  if seen[i]:continue

  cc = dfs2(i)

  scc.append(cc)

  

print((len(scc)))

for cc in scc:

  print((len(cc),*cc))
N,M = list(map(int,input().split()))

G1 = [[] for _ in range(N)]

G2 = [[] for _ in range(N)]

for i in range(M):

  a,b=list(map(int,input().split()))

  G1[a].append(b)

  G2[b].append(a)

  

def argsort(arr, reverse=False, shift=20):

    N = len(arr)

    tmp=[0]*N

    for i in range(N):

        tmp[i] = (arr[i] << shift) | i

    tmp = sorted(tmp,reverse=reverse)

    out=[0]*N

    mask = (1<<shift) - 1

    for j in range(N):

        i = tmp[j] & mask

        out[j] = i

    return out



def dfs(a0,seen,postorder,order):

    todo = [~a0, a0]

    while todo:

        a = todo.pop()

        if a >= 0:

            seen[a] = 1

            for b in G1[a]:

                if seen[b]: continue

                todo.append(~b)

                todo.append(b)

        else:

          if postorder[~a] == -1:

            postorder[~a] = order

            order += 1

    return seen,postorder,order

  

def dfs2(v,seen):

    todo = [v]

    seen[v] = 1

    cc = [v]

    while todo:

        v = todo.pop()

        for next_v in G2[v]:

            if seen[next_v]: continue

            seen[next_v] = 1

            todo.append(next_v)

            cc.append(next_v)

    return cc,seen

  

def scc(G1,G2):

  N = len(G1)

  seen = [0]*N

  postorder=[-1]*N

  order = 0

  for i in range(N):

    if seen[i]:continue

    seen,postorder,order = dfs(i,seen,postorder,order)



  seen = [0]*N

  scclist = []

  for i in argsort(postorder,reverse=True):

    if seen[i]:continue

    cc,seen = dfs2(i,seen)

    scclist.append(cc)

  return scclist



def main():

  scclist = scc(G1,G2)

  print((len(scclist)))

  for cc in scclist:

    print((len(cc),*cc))

    

if __name__=="__main__":

  main()
N, M = list(map(int, input().split()))
G1 = [[] for _ in range(N)]
G2 = [[] for _ in range(N)]
for i in range(M):
    a, b = list(map(int, input().split()))
    if a == b:
        continue
    G1[a].append(b)
    G2[b].append(a)


def dfs(a0):
    global order
    todo = [~a0, a0]
    while todo:
        a = todo.pop()
        if a >= 0:
            seen[a] = 1
            for b in G1[a]:
                if seen[b]:
                    continue
                todo.append(~b)
                todo.append(b)
        else:
            if postorder[~a] == -1:
                postorder[~a] = order
                order += 1
    return


def dfs2(v):
    todo = [v]
    seen[v] = 1
    cc = [v]
    while todo:
        v = todo.pop()
        for next_v in G2[v]:
            if seen[next_v]:
                continue
            seen[next_v] = 1
            todo.append(next_v)
            cc.append(next_v)
    return cc


seen = [0] * N
postorder = [-1] * N
order = 0
for i in range(N):
    if seen[i]:
        continue
    dfs(i)
seen = [0] * N
scc = []
for i, _ in sorted(enumerate(postorder), key=lambda x: x[1], reverse=True):
    if seen[i]:
        continue
    cc = dfs2(i)
    scc.append(cc)
print((len(scc)))
for cc in scc:
    print((len(cc), *cc))

N, M = list(map(int, input().split()))
G1 = [[] for _ in range(N)]
G2 = [[] for _ in range(N)]
for i in range(M):
    a, b = list(map(int, input().split()))
    G1[a].append(b)
    G2[b].append(a)


def argsort(arr, reverse=False, shift=20):
    N = len(arr)
    tmp = [0] * N
    for i in range(N):
        tmp[i] = (arr[i] << shift) | i
    tmp = sorted(tmp, reverse=reverse)
    out = [0] * N
    mask = (1 << shift) - 1
    for j in range(N):
        i = tmp[j] & mask
        out[j] = i
    return out


def dfs(a0, seen, postorder, order):
    todo = [~a0, a0]
    while todo:
        a = todo.pop()
        if a >= 0:
            seen[a] = 1
            for b in G1[a]:
                if seen[b]:
                    continue
                todo.append(~b)
                todo.append(b)
        else:
            if postorder[~a] == -1:
                postorder[~a] = order
                order += 1
    return seen, postorder, order


def dfs2(v, seen):
    todo = [v]
    seen[v] = 1
    cc = [v]
    while todo:
        v = todo.pop()
        for next_v in G2[v]:
            if seen[next_v]:
                continue
            seen[next_v] = 1
            todo.append(next_v)
            cc.append(next_v)
    return cc, seen


def scc(G1, G2):
    N = len(G1)
    seen = [0] * N
    postorder = [-1] * N
    order = 0
    for i in range(N):
        if seen[i]:
            continue
        seen, postorder, order = dfs(i, seen, postorder, order)
    seen = [0] * N
    scclist = []
    for i in argsort(postorder, reverse=True):
        if seen[i]:
            continue
        cc, seen = dfs2(i, seen)
        scclist.append(cc)
    return scclist


def main():
    scclist = scc(G1, G2)
    print((len(scclist)))
    for cc in scclist:
        print((len(cc), *cc))


if __name__ == "__main__":
    main()

-    if a == b: -        continue -def dfs(a0): -    global order +def argsort(arr, reverse=False, shift=20): +    N = len(arr) +    tmp = [0] * N +    for i in range(N): +        tmp[i] = (arr[i] << shift) | i +    tmp = sorted(tmp, reverse=reverse) +    out = [0] * N +    mask = (1 << shift) - 1 +    for j in range(N): +        i = tmp[j] & mask +        out[j] = i +    return out + + +def dfs(a0, seen, postorder, order): -    return +    return seen, postorder, order -def dfs2(v): +def dfs2(v, seen): -    return cc +    return cc, seen -seen = [0] * N -postorder = [-1] * N -order = 0 -for i in range(N): -    if seen[i]: -        continue -    dfs(i) -seen = [0] * N -scc = [] -for i, _ in sorted(enumerate(postorder), key=lambda x: x[1], reverse=True): -    if seen[i]: -        continue -    cc = dfs2(i) -    scc.append(cc) -print((len(scc))) -for cc in scc: -    print((len(cc), *cc)) +def scc(G1, G2): +    N = len(G1) +    seen = [0] * N +    postorder = [-1] * N +    order = 0 +    for i in range(N): +        if seen[i]: +            continue +        seen, postorder, order = dfs(i, seen, postorder, order) +    seen = [0] * N +    scclist = [] +    for i in argsort(postorder, reverse=True): +        if seen[i]: +            continue +        cc, seen = dfs2(i, seen) +        scclist.append(cc) +    return scclist + + +def main(): +    scclist = scc(G1, G2) +    print((len(scclist))) +    for cc in scclist: +        print((len(cc), *cc)) + + +if __name__ == "__main__": +    main()