

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 = list(map(int, input().split()))



    E = []

    for _ in range(M):

        a, b = list(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()



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 = list(map(int, input().split()))



    E = []

    for _ in range(M):

        a, b = list(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 list(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()

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 = list(map(int, input().split()))
    E = []
    for _ in range(M):
        a, b = list(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()

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 = list(map(int, input().split()))
    E = []
    for _ in range(M):
        a, b = list(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 list(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()

+    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) -    done = set() -    o = [] -    for v in V: -        if v in done: -            continue -        dfs(v, done, o) +    # done = set() +    # oo = [] +    # for v in V: +    #     if v in done: +    #         continue +    #     dfs(v, done, oo) +    # print(o) +    # print(oo) -    vv = scc(g) +    V = list(range(1, 11)) +    E = [] +    for u, e in list(g.items()): +        for v in e: +            E.append((u, v)) +    vv = scc(V, E)