#include <fstream>
#include <vector>
#include <stack>
struct Vertex
{
int x;
std::vector<int> myV;
Vertex() : x(), myV() {}
Vertex(int a) : x(a), myV() {}
};
void visitA(Vertex *A, int y, bool *bC, std::stack<int> &myS);
void visitB(Vertex *B, int y, bool *bC, std::vector<std::vector<int> > &strong, int nr);
void dfsA(Vertex *A, int nV, std::stack<int> &myS);
void dfsB(Vertex *B, int nV, std::stack<int> &myS, std::ostream& out);
int main()
{
std::ifstream in("ctc.in");
std::ofstream out("ctc.out");
int nV, nE, a, b;
in >> nV >> nE;
Vertex *A = new Vertex[nV + 1], *B = new Vertex[nV + 1];
for(int i = 1; i <= nV; i++)
A[i] = Vertex(i), B[i] = Vertex(i);
for(int i = 0; i < nE; i++)
{
in >> a >> b;
A[a].myV.push_back(b);
B[b].myV.push_back(a);
}
std::stack<int> myS;
dfsA(A, nV, myS);
dfsB(B, nV, myS, out);
return 0;
}
void dfsB(Vertex *B, int nV, std::stack<int> &myS, std::ostream& out)
{
int nr = 0, a;
std::vector<std::vector<int> > strong;
bool *bC = new bool[nV + 1];
for(int i = 1; i <= nV; i++)
bC[i] = false;
while(!myS.empty())
{
a = myS.top();
myS.pop();
if(bC[a]) continue;
strong.push_back(std::vector<int>());
visitB(B, a, bC, strong, nr);
nr++;
}
out << strong.size() << '\n';
for(unsigned i = 0; i < strong.size(); i++)
{
for(unsigned j = 0; j < strong[i].size(); j++)
out << strong[i][j] << ' ';
out << '\n';
}
}
void visitB(Vertex *B, int y, bool *bC, std::vector<std::vector<int> > &strong, int nr)
{
bC[y] = true;
for(unsigned i = 0; i < B[y].myV.size(); i++)
if(!bC[B[y].myV[i]]) visitB(B, B[y].myV[i], bC, strong, nr);
strong[nr].push_back(y);
}
void visitA(Vertex *A, int y, bool *bC, std::stack<int> &myS)
{
bC[y] = true;
for(unsigned i = 0; i < A[y].myV.size(); i++)
if(!bC[A[y].myV[i]]) visitA(A, A[y].myV[i], bC, myS);
myS.push(y);
}
void dfsA(Vertex *A, int nV, std::stack<int> &myS)
{
bool *bC = new bool[nV + 1];
for(int i = 1; i <= nV; i++)
bC[i] = false;
for(int i = 1; i <= nV; i++)
if(!bC[i]) visitA(A, i, bC, myS);
}