#include <bits/stdc++.h>
using namespace std;
const int inf = 1e9;
const int maxn = 2e5;
int num[maxn];
int par[maxn];
int get_p(int x) {
  if (par[x] == x) return x;
  int cur = get_p(par[x]);
  par[x] = cur;
  return cur;
}
void unit(int u, int v) {
  u = get_p(u);
  v = get_p(v);
  if (u == v) return;
  if (num[v] > num[u]) swap(u, v);
  par[v] = u;
  num[u] += num[v];
}
void init() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
}
vector<vector<int>> g;
int main() {
  init();
  fill(num, num + maxn, 1);
  for (int i = 0; i < maxn; i++) par[i] = i;
  int n, m;
  cin >> n >> m;
  g.resize(n);
  int ans = 0;
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    u--;
    v--;
    g[max(u, v)].push_back(min(u, v));
  }
  unordered_set<int> curh;
  curh.insert(0);
  for (int i = 1; i < n; i++) {
    curh.insert(i);
    unordered_map<int, int> foo;
    for (auto ev : g[i]) {
      foo[get_p(ev)]++;
    }
    unordered_set<int> curp;
    for (auto ev : curh) {
      if (num[get_p(ev)] == foo[get_p(ev)]) continue;
      unit(i, ev);
    }
    for (auto ev : curh) curp.insert(get_p(ev));
    curh = curp;
  }
  unordered_set<int> bar;
  for (int i = 0; i < n; i++) bar.insert(get_p(i));
  cout << bar.size() - 1;
  return 0;
}
