#include<bits/stdc++.h>
using namespace std;
const int N = 10005;
int n,m;
vector e (N,vector<int>());
vector ne (N,vector<int>());
vector<int>dfn(N) , low(N), stk(N),instk(N);
int tot,top,cnt;
vector<int>scc(N);
vector<int> w(N),nw(N),dp(N);
vector path(N,vector<int>());
void tarjan(int x){
dfn[x]=low[x]=++tot;
stk[++top]=x,instk[x]=1;
for(int y : e[x]){
if(!dfn[y]){
tarjan(y);
low[x] = min(low[x],low[y]);
}
else if(instk[y])
low[x]=min(low[x],dfn[y]);
}
if(dfn[x]==low[x]){
int y;++cnt;
do{
y=stk[top--];
instk[y]=0;
scc[y]=cnt;
path[cnt].push_back(y);
}while(y!=x);
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
e[u].push_back(v);
}
for(int i=1;i<=n;i++){
if(!dfn[i])tarjan(i);
}
//执行完之后有scc[i]=x(根据连通分量不同有不同的x);x取值1-cnt,cnt为总的连通分量个数
cout<<cnt<<endl;
vector<bool>vs(N,false);
for(int i=1;i<=n;i++){
int x = scc[i];
auto v = path[x];
if(vs[x]==false){
sort(v.begin(),v.end());
for(auto t : v){
cout<<t<<" ";
}
cout<<endl;
}
vs[x]=true;
}
}