#include <iostream>
#include <fstream>
#include <vector>
void DFS(std::vector<int> graph[], bool viz[], int k, std::vector<int> &postordine) {
viz[k] = true;
for (size_t i = 0; i < graph[k].size(); i++) {
if (!viz[graph[k][i]]) {
DFS(graph, viz, graph[k][i], postordine);
}
}
postordine.push_back(k);
}
void DFST(std::vector<int> graphT[], bool viz[], int k, std::vector<int> components[], int nr) {
viz[k] = false;
components[nr].push_back(k);
for (size_t i = 0; i < graphT[k].size(); i++) {
if (viz[graphT[k][i]]) {
DFST(graphT, viz, graphT[k][i], components, nr);
}
}
}
void readGraphs(std::vector<int> graph[], std::vector<int> graphT[], int &n, int &m) {
std::ifstream fin("ctc.in");
int x, y;
fin >> n >> m;
for (size_t i = 0; i < m; i++) {
fin >> x >> y;
graph[x].push_back(y);
graphT[y].push_back(x);
}
fin.close();
}
int main(int argc, char *argv[]) {
int n, m;
bool viz[5001] = { false };
int nrComponenteTareConexe = 0;
std::vector<int> graph[5001], graphT[5001], postordine;
std::vector<int> components[5001];
readGraphs(graph, graphT, n, m);
for (size_t i = 1; i <= n; i++) {
if (!viz[i]) {
DFS(graph, viz, i, postordine);
}
}
for (int i = postordine.size(); i >= 0; i--) {
if (viz[postordine[i]]) {
nrComponenteTareConexe++;
DFST(graphT, viz, postordine[i], components, nrComponenteTareConexe);
}
}
std::ofstream fout("ctc.out");
fout << nrComponenteTareConexe << "\n";
for (int i = 1; i <= nrComponenteTareConexe; i++) {
for (int j = components[i].size() - 1; j >= 0; j--) {
fout << components[i][j] << " ";
}
fout << "\n";
}
fout.close();
return 0;
}