#include <bits/stdc++.h>
using namespace std;
#define _ ios_base::sync_with_stdio(false);cout.precision(30);cout.tie(0);cin.tie(0);
#define ll long long
#define ld long double
#define rep(i, a, b) for(__typeof(b)i=(a)-((a)>(b));i!=(b)-((a)>(b));i+=1-2*((a)>(b)))
#define whilet() ll t;cin>>t;while(t--)
#define all(c) (c).begin(), (c).end()
template <class TCost>
class Graph {
public:
struct Edge {
int from, to;
TCost cost;
Edge(int _from, int _to, TCost _cost): from(_from), to(_to), cost(_cost) {};
};
int size;
bool zeroIndexed;
vector<Edge> edges;
vector<vector<pair<int, TCost>>> adjacencyList;
Graph() {};
Graph(int _size, bool _zeroIndexed = true) {
zeroIndexed = _zeroIndexed;
if (!zeroIndexed) _size++;
size = _size;
adjacencyList.resize(_size);
};
~Graph() = default;
};
template <class TCost>
class DirectedGraph : public Graph<TCost> {
public:
DirectedGraph() {};
DirectedGraph(int _size, bool _zeroIndexed): Graph<TCost>(_size, _zeroIndexed) {};
DirectedGraph(int _size): Graph<TCost>(_size) {};
void addEdge(int from, int to, TCost cost = 0) {
this->edges.push_back({from, to, cost});
this->adjacencyList[from].push_back({to, cost});
}
void printEdges() {
for (auto edge: this->edges) {
cout << edge.from << ' ' << edge.to << endl;
}
}
};
template <class TCost>
class SCC {
public:
static void TarjanRecursion(
int v,
int &indexCount,
vector<int> &index,
vector<int> &low,
stack<int> &S,
DirectedGraph<TCost> &graph,
vector<bool> &onStack,
vector<vector<int>> &components
) {
index[v] = indexCount;
low[v] = indexCount;
indexCount++;
S.push(v);
onStack[v] = true;
for (auto edge: graph.adjacencyList[v]) {
int w = edge.first;
if (!index[w]) {
TarjanRecursion(w, indexCount, index, low, S, graph, onStack, components);
low[v] = min(low[v], low[w]);
} else if (onStack[w]) {
low[v] = min(low[v], index[w]);
}
}
if (low[v] == index[v]) {
vector<int> component;
int w;
do {
w = S.top();
S.pop();
onStack[w] = false;
component.push_back(w);
} while (w != v);
components.push_back(component);
}
}
static vector<vector<int>> Tarjan(DirectedGraph<TCost> graph) {
int indexCount = 1;
vector<int> index(graph.size), low(graph.size);
vector<bool> onStack(graph.size);
stack<int> S;
vector<vector<int>> components;
for (int i=(graph.zeroIndexed?0:1); i<graph.size; i++) {
if (!index[i]) {
TarjanRecursion(i, indexCount, index, low, S, graph, onStack, components);
}
}
return components;
}
};
ifstream fi("ctc.in");
ofstream fo("ctc.out");
int n,m;
int main() {_
fi >> n >> m;
DirectedGraph<int> g(n, false);
rep(i,0,m) {
int x,y;
fi >> x >> y;
g.addEdge(x,y);
}
auto rs = SCC<int>::Tarjan(g);
fo << rs.size() << endl;
for (auto x:rs) {
for (auto y:x) fo << y << ' ';
fo << endl;
}
return 0;
}