#include <bits/stdc++.h>
#pragma GCC optimize("O3")
using namespace std;
template <class c>
struct rge {
  c b, e;
};
template <class c>
rge<c> range(c i, c j) {
  return rge<c>{i, j};
}
template <class c>
auto dud(c* x) -> decltype(cerr << *x, 0);
template <class c>
char dud(...);
struct debug {
  template <class c>
  debug& operator<<(const c&) {
    return *this;
  }
};
const long long N = 1e5 + 5;
unordered_set<long long> ss[5 * N];
unordered_set<long long> s2;
vector<long long> ans;
void bfs(long long uu) {
  queue<long long> qq;
  qq.push(uu);
  s2.erase(uu);
  while (!qq.empty()) {
    long long u = qq.front();
    qq.pop();
    ans.push_back(u);
    vector<long long> ans1;
    for (long long v : s2) {
      if (ss[u].find(v) == ss[u].end()) {
        ans1.push_back(v);
        qq.push(v);
      }
    }
    for (long long j : ans1) {
      s2.erase(j);
    }
  }
}
int32_t main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  long long n, m;
  cin >> n >> m;
  long long a, b;
  for (long long i = 0; i < m; i++) {
    cin >> a >> b;
    ss[a].insert(b);
    ss[b].insert(a);
  }
  for (long long i = 1; i <= n; i++) {
    s2.insert(i);
  }
  vector<vector<long long> > res;
  for (long long i = 1; i <= n; i++) {
    if (s2.find(i) != s2.end()) {
      bfs(i);
      res.push_back(ans);
      ans.clear();
    }
  }
  cout << (long long)res.size() << "\n";
  for (vector<long long> i : res) {
    cout << (long long)i.size() << " ";
    for (long long j : i) {
      cout << j << " ";
    }
    cout << "\n";
  }
  return 0;
}
