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

class SCC {
private:
  const int N;
  vector<vector<int>> G;
  vector<vector<int>> R;
  vector<int> ord, low;
  stack<int> st;
  void dfs(const int u, int &tm) {
    ord.at(u) = low.at(u) = tm++, st.push(u);
    for (int v : G.at(u)) {
      if (ord.at(v) < 0) {
        dfs(v, tm);
        low.at(u) = min(low.at(u), low.at(v));
      } else if (cmp.at(v) < 0) {
        low.at(u) = min(low.at(u), ord.at(v));
      }
    }
    if (ord.at(u) == low.at(u)) {
      R.push_back(vector<int>{});
      while (true) {
        const int v = st.top();
        st.pop();
        cmp.at(v) = cnt;
        R.back().push_back(v);
        if (v == u) break;
      }
      cnt++;
    }
  }

public:
  vector<vector<int>> graph;
  vector<int> cmp;
  int cnt;
  SCC(const int n) : N(n), G(n), ord(n, -1), low(n), cmp(n, -1), cnt(0) {}
  void add(const int from, const int to) { G.at(from).push_back(to); }
  vector<vector<int>> solve() {
    int tm = 0;
    for (int i = 0; i < N; i++) {
      if (ord.at(i) < 0) dfs(i, tm);
    }
    for (int i = 0; i < N; i++) cmp.at(i) = cnt - 1 - cmp.at(i);
    reverse(R.begin(), R.end());
    return R;
  }
  vector<vector<int>> build() {
    graph.resize(cnt);
    for (int i = 0; i < N; i++) {
      for (int j : G.at(i)) {
        if (cmp.at(i) != cmp.at(j)) {
          graph.at(cmp.at(i)).push_back(cmp.at(j));
        }
      }
    }
    return graph;
  }
};

signed main() {
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);

  int N, M;
  cin >> N >> M;
  SCC SC(N);
  for (int i = 0; i < M; i++) {
    int a, b;
    cin >> a >> b;
    SC.add(a, b);
  }

  auto G = SC.solve();
  cout << G.size() << "\n";
  for (int i = 0, h = G.size(); i < h; i++) {
    cout << G.at(i).size();
    for (int j = 0, w = G.at(i).size(); j < w; j++) {
      cout << " " << G.at(i).at(j);
    }
    cout << "\n";
  }
}