//#include "bits/stdc++.h"

#define _USE_MATH_DEFINES
#include<cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <deque>
#include <algorithm>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <unordered_map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#include <iterator>
#include<iomanip>
#include<complex>
#include<assert.h>

using namespace std;

#define rep(i,a,b) for(int i=(a), i##_len=(b);i<i##_len;i++)
#define rrep(i,a,b) for(int i=(b)-1;i>=(a);i--)
#define all(c) begin(c),end(c)

#define int ll
#define SZ(x) ((int)(x).size())
#define pb push_back
#define mp make_pair

//typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef pair<int, double> pid;
typedef pair<double, int> pdi;
typedef pair<double, double> pdd;
typedef vector< vector<int> > mat;

template<class T> bool chmax(T &a, const T &b) { if (a < b) { a = b; return true; } return false; }
template<class T> bool chmin(T &a, const T &b) { if (b < a) { a = b; return true; } return false; }

const int INF = sizeof(int) == sizeof(long long) ? 0x3f3f3f3f3f3f3f3fLL : 0x3f3f3f3f;
const int MOD = (int)1e9 + 7;

const double EPS = 1e-9;

/*template<int MV> class SCC {
public:
	int V;
	vector<vector<int> > SC;
	vector<int> SCID, REV;
private:
	vector<int> E[MV], RE[MV], NUM; int vis[MV];
public:
	void init(int V) { this->V = V; for (int i = 0; i < MV; i++) { E[i].clear(); RE[i].clear(); } }
	void add_edge(int x, int y) { E[x].push_back(y); RE[y].push_back(x); }
	void dfs(int cu) { vis[cu] = 1; for (int i = 0; i < E[cu].size(); i++) if (!vis[E[cu][i]]) dfs(E[cu][i]); NUM.push_back(cu); }
	void revdfs(int cu, int ind) {
		int i; vis[cu] = 1; SCID[cu] = ind; SC[ind].push_back(cu); REV[cu] = ind;
		rep(i, 0, RE[cu].size()) if (!vis[RE[cu][i]]) revdfs(RE[cu][i], ind);
	}
	void scc() {
		int c = 0; SC.clear(); SC.resize(MV); NUM.clear();
		ZERO(vis); for (int i = 0; i < V; i++) if (!vis[i]) dfs(i);
		ZERO(vis); for (int i = NUM.size() - 1; i >= 0; i--) if (!vis[NUM[i]]) {
			SC[c].clear(); revdfs(NUM[i], c); sort(SC[c].begin(), SC[c].end()); c++;
		}
		SC.resize(c);
	}
};*/

struct SCC {
	int V;
	vector<vector<int> > SC;
	vector<int> SCID, REV;

	vector<vector<int>> G, RG;
	vector<int> NUM;
	vector<bool> used;

	SCC(int V) :V(V)
	{
		SC.resize(V);
		SCID = vector<int>(V, -1);
		REV = vector<int>(V, -1);
		G = vector<vector<int>>(V);
		RG = vector<vector<int>>(V);
		used = vector<bool>(V, false);
	}

	void add_edge(int x, int y)
	{
		G[x].push_back(y);
		RG[y].push_back(x);
	}
	void dfs(int v)
	{
		used[v] = true;
		for (auto e : G[v])
		{
			if (!used[e])dfs(e);
		}
		NUM.push_back(v);
	}
	void revdfs(int v, int idx)
	{
		int i; 
		used[v] = true;
		SCID[v] = idx;
		SC[idx].push_back(v); 
		REV[v] = idx;
		for (auto e : RG[v])
		{
			if (!used[e])revdfs(e, idx);
		}
	}
	void scc()
	{
		int c = 0; 
		fill(all(used), false);
		for (int i = 0; i < V; i++)
		{
			if (!used[i]) dfs(i);
		}
		fill(all(used), false);
		for (int i = NUM.size() - 1; i >= 0; i--)
		{
			if (!used[NUM[i]]) 
			{
				revdfs(NUM[i], c); 
				sort(all(SC[c]));
				c++;
			}
		}
		SC.resize(c);
	}
};

signed main()
{
	cin.tie(0);
	ios::sync_with_stdio(false);

	int V, E;
	cin >> V >> E;

	SCC scc(V);
	int x, y;
	rep(i, 0, E)
	{
		cin >> x >> y;
		scc.add_edge(x, y);
	}

	scc.scc();

	cout << SZ(scc.SC) << endl;
	for (const auto& v : scc.SC)
	{
		cout << SZ(v) << " ";
		rep(i, 0, SZ(v))
		{
			cout << v[i];
			if (i == SZ(v) - 1)cout << endl;
			else cout << " ";
		}
	}

	return 0;
}

Measured memory_bytes: 88664