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) (judge verdict: Accepted)

#include <vector>
#include <algorithm>
#include <cstddef>

struct strongly_connected_component {
	using size_type = std::size_t;
private : 
	std::vector<std::vector<size_type>> g, revg;
	std::vector<size_type> order, index;
	std::vector<bool> seen;

	void dfs (size_type v) {
		seen[v] = true;
		for (const size_type &u : g[v]) {
			if (not seen[u]) dfs(u);
		}
		order.push_back(v);
	}

	void dfs2 (size_type v, const size_type idx) {
		seen[v] = true; index[v] = idx;
		for (const size_type &u : revg[v]) {
			if (not seen[u]) dfs2(u, idx);
		}
	}

public : 
	strongly_connected_component (size_type n)
	noexcept : g(n), revg(n), index(n), seen(n) { order.reserve(n); }

	void add_edge (size_type u, size_type v) noexcept {
		g[u].push_back(v);
		revg[v].push_back(u);
	}

	size_type solve () noexcept {
		size_type idx = 0;
		order.clear();
		std::fill(seen.begin(), seen.end(), false);
		for (size_type v = 0; v < g.size(); v++) if (not seen[v]) dfs(v);
		std::fill(seen.begin(), seen.end(), false);
		std::reverse(order.begin(), order.end());
		for (const size_type &v : order) if (not seen[v]) dfs2(v, idx++);
		return idx;
	}

	std::vector<std::vector<size_type>> build () noexcept {
		std::vector<int> count(solve());
		std::vector<std::vector<size_type>> tpls(count.size());
		for (size_type i = 0; i < g.size(); i++) count[index[i]]++;
		for (size_type i = 0; i < count.size(); i++) tpls[i].reserve(count[i]);
		for (size_type i = 0; i < g.size(); i++) tpls[index[i]].push_back(i);
		return tpls;
	}

	const size_type &operator[] (size_type v) const noexcept {
		return index[v];
	}

};


#include <iostream>

using usize = std::size_t;

int main() {
	usize n, m;
	std::cin >> n >> m;
	strongly_connected_component scc(n);
	for (usize i = 0; i < m; i++) {
		usize a, b;
		std::cin >> a >> b;
		scc.add_edge(a, b);
	}
	
	auto ans = scc.build();
	std::cout << ans.size() << '\n';
	for (const auto &v : ans) {
		std::cout << v.size();
		for (const auto &e : v) std::cout << ' ' << e;
		std::cout << '\n';
	}
	
	return 0;
}