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 in C++ (GCC 9.2.1 with AC Library v1.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define ALL(v) (v).begin(), (v).end()
using ll = long long;
constexpr int INF = 1e9;
constexpr long long LINF = 1e18;
constexpr long long MOD = 1e9 + 7;

struct SCC {
    int n;
    vector<vector<int>> G, R, T;
    vector<bool> used;
    vector<int> vs, cmp;

    SCC(int n) : n(n), G(n), R(n), used(n), cmp(n) {}

    int operator[](int k) {
        return cmp[k];
    };

    void add_edge(int from, int to) {
        G[from].emplace_back(to);
        R[to].emplace_back(from);
    }

    void dfs(int v) {
        used[v] = true;
        for (int u : G[v]) {
            if (!used[u]) dfs(u);
        }
        vs.emplace_back(v);
    }

    void rdfs(int v, int k) {
        used[v] = true;
        cmp[v] = k;
        for (int u : R[v]) {
            if (!used[u]) rdfs(u, k);
        }
    }

    int build() {
        for (int v = 0; v < n; v++) {
            if (!used[v]) dfs(v);
        }
        fill(used.begin(), used.end(), false);
        int k = 0;
        for (int i = n - 1; i >= 0; i--) {
            if (!used[vs[i]]) {
                rdfs(vs[i], k);
                k++;
            }
        }
        T.resize(k, vector<int>());
        for (int v = 0; v < n; v++) {
            for (int u : G[v]) {
                if (cmp[v] != cmp[u]) T[cmp[v]].emplace_back(cmp[u]);
            }
        }
        for (int i = 0; i < k; i++) {
            sort(T[i].begin(), T[i].end());
            T[i].erase(unique(T[i].begin(), T[i].end()), T[i].end());
        }
        return k;
    }
};

signed main() {
    int n, m;
    cin >> n >> m;
    SCC scc(n);
    int a, b;
    rep(i, m) {
        cin >> a >> b;
        scc.add_edge(a, b);
    }
    int k = scc.build();
    cout << k << endl;
    vector<int> vec[k];
    rep(v, n) {
        vec[scc[v]].emplace_back(v);
    }
    for (auto v : vec) {
        cout << v.size();
        for (int u : v) {
            cout << " " << u;
        }
        cout << endl;
    }
    return 0;
}