#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;

#ifdef _LOCAL
  #include <utils/debug.hpp>
  #include <utils/random_generate.hpp>
  #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
  #define debug(...) 42
  #define generate_string(...) 42
  #define generate_array(...) 42
  #define generate_unique_array(...) 42
#endif

typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vl2;
const bool multiple_queries = false;
#define rep(i, n) for(ll i = 0; i < (n) ; ++i)
#define For(i, a, b) for(ll i = (a); i < (b) ; ++i)
#define revrep(i, n) for(ll i = (n) - 1; i >= 0 ; --i)
#define revFor(i, b, a) for(ll i = (b) - 1; i >= (a) ; --i)
#define all(v) v.begin(), v.end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcount(i) __builtin_popcountl((i))
#define substring(s, start, end) s.substr((start), (end) - (start) + 1)

void scan(){}
template <class Head, class... Tail>
void scan(Head&& head, Tail&&... tail) {
  cin >> head;
  scan(forward<Tail>(tail)...);
}

void print(){}
void println(){cout << endl;}

template <class Head, class... Tail>
void print(Head&& head, Tail&&... tail) {
  cout << head;
  if (sizeof...(tail) != 0) cout << " ";
  print(forward<Tail>(tail)...);
}

template <class T>
void print(vector<T>& vs){
  for (auto v: vs){
    cout << v;
    if (&v != &vs.back()) cout << " ";
  }
  cout << endl;
}

template <class Head, class... Tail>
void println(Head&& head, Tail&&... tail) {
  cout << head;
  if (sizeof...(tail) != 0) cout << " ";
  println(forward<Tail>(tail)...);
}

template <class T>
void println(vector<T>& vs){for (auto v: vs) cout << v << endl;}

struct StronglyConnectedComponents{
  /*
  dag: [cmp idx][# of connected cmp]
    the index of connected cmp
  cmp: [cmp idx][# of vertex included in a cmp]
    the index of vertex
  cmp_idx: [vertex idx]
    the component which the vertex belongs to

  Use graph_rev when you would like to know the vertex with zero indegree
  */
  ll n, n_cmp;
  vl2 graph, graph_rev, dag, cmp;
  vl order, visited, cmp_idx;

  StronglyConnectedComponents(){}
  StronglyConnectedComponents(ll sz):
    n(sz), graph(sz), graph_rev(sz),
    visited(sz), cmp_idx(sz){}

  void add_edge(ll from, ll to){
    graph[from].push_back(to);
    graph_rev[to].push_back(from);
  }

  void input(ll m, ll offset = -1){
    ll a, b;
    rep(i, m){
      cin >> a >> b;
      add_edge(a + offset, b + offset);
    }
  }

  ll operator[](ll k){return cmp_idx[k];}

  void dfs_fwd(ll source){
    visited[source] = 1;
    rep(i, ll(graph[source].size())){
      ll target = graph[source][i];
      if (!visited[target]) dfs_fwd(target);
    }
    order.push_back(source);
  }

  void dfs_bwd(ll source, ll num){
    visited[source] = 1, cmp_idx[source] = num;

    cmp[num].push_back(source);
    rep(i, ll(graph_rev[source].size())){
      ll target = graph_rev[source][i];
      if (!visited[target]) dfs_bwd(target, num);
    }
  }

  ll build(){
    fill(all(visited), 0);
    order.clear();
    rep(i, n)
      if (!visited[i]) dfs_fwd(i);

    fill(all(visited), 0);
    ll num = 0;
    revrep(i, ll(order.size())){
      if (!visited[order[i]]){
        dag.push_back(vl());
        cmp.push_back(vl());
        dfs_bwd(order[i], num++);
      }
    }

    rep(i, n) for (ll to: graph[i])
      if (cmp_idx[i] != cmp_idx[to])
        dag[cmp_idx[i]].push_back(cmp_idx[to]);

    rep(i, num){
      sort(all(dag[i]));
      dag[i].erase(unique(all(dag[i])), dag[i].end());
    }
    return n_cmp = num;
  }

  // if the v-th vertex is in loop or not
  bool in_loop(ll v){return cmp[cmp_idx[v]].size() > 1;}

  // if the dag has loops or not
    bool has_loop(){
    rep(i, ll(cmp.size())) if (cmp[i].size() > 1) return true;
    return false;
  }
};

void solve(){
  ll n, m;
  scan(n, m);
  StronglyConnectedComponents scc(n);
  rep(i, m){
    ll a, b;
    scan(a, b);
    scc.add_edge(a, b);
  }

  println(scc.build());
  for (auto& vs: scc.cmp){
    print(vs.size(), "");
    for (auto& v: vs) print(v, "");
    println();
  }
}

void test(ll num = 0, bool verbose = false){
  rep(i, max(1LL, num)){
    ll t = clock();
    if (verbose) cout << "\n#####" << " " << i + 1 << " " << "#####" << " " << "\n## Answer ##\n";
    solve();
    if (verbose) {cout << "\nElapsed Time:" << " " << 1000.0 * (clock() - t) / CLOCKS_PER_SEC << " " << "[ms]" << endl;}
  }
}

int main(void){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(15);
  #ifdef _LOCAL
    test(6, true);
  #else
    ll t = 0;
    if (multiple_queries) cin >> t;
    test(t, false);
  #endif
  return 0;
}

Measured memory_bytes: 111528