#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
const int MAXN = 100005;
vector<int> adj[MAXN];
vector<int> adj_rev[MAXN];
bool visited[MAXN];
vector<int> order;
vector<vector<int>> ctc;
vector<int> current_comp;
void dfs1(int u) {
visited[u] = true;
for (int v : adj[u]) {
if (!visited[v]) {
dfs1(v);
}
}
order.push_back(u);
}
void dfs2(int u) {
visited[u] = true;
current_comp.push_back(u);
for (int v : adj_rev[u]) {
if (!visited[v]) {
dfs2(v);
}
}
}
int main() {
ifstream cin("ctc.in");
ofstream cout("ctc.out");
int n, m;
cin >> n >> m;
for (int i = 0; i < m; ++i) {
int u, v;
cin >> u >> v;
adj[u].push_back(v);
adj_rev[v].push_back(u);
}
for (int i = 1; i <= n; ++i) {
if (!visited[i]) {
dfs1(i);
}
}
// Resetăm vectorul de vizitat
for (int i = 1; i <= n; ++i) {
visited[i] = false;
}
while (!order.empty()) {
int u = order.back();
order.pop_back();
if (!visited[u]) {
current_comp.clear();
dfs2(u);
ctc.push_back(current_comp);
}
}
cout << ctc.size() << "\n";
for (int i = 0; i < ctc.size(); ++i) {
for (int j = 0; j < ctc[i].size(); ++j) {
cout << ctc[i][j] << " ";
}
cout << "\n";
}
return 0;
}