#include <bits/stdc++.h>
using namespace std;
int dadsadasda;
const int INF = 0x3f3f3f3f;
const long long LLINF = 1e18;
const int MAXN = 2e5;
int n, m;
vector<int> E[MAXN];
int father[MAXN], siz[MAXN], cnt[MAXN];
set<int> reprs;
int find(int x) {
  if (father[x] == -1) return x;
  return father[x] = find(father[x]);
}
void unio(int x, int y) {
  if (siz[x] > siz[y]) {
    father[y] = x;
    cnt[x] += cnt[y];
  } else {
    father[x] = y;
    cnt[y] += cnt[x];
    if (siz[x] == siz[y]) siz[y]++;
  }
}
int main() {
  dadsadasda = scanf("%d %d", &n, &m);
  for (int i = 0; i < m; i++) {
    int a, b;
    dadsadasda = scanf("%d %d", &a, &b);
    a--, b--;
    if (a > b) swap(a, b);
    E[b].push_back(a);
  }
  for (int x = 0; x < n; x++) {
    father[x] = -1;
    siz[x] = 0;
    cnt[x] = 1;
    unordered_map<int, int> one_edges;
    one_edges.reserve((int)E[x].size());
    for (int y : E[x]) one_edges[find(y)]++;
    for (auto y : reprs) {
      if (cnt[y] > one_edges[y] && y != find(x)) unio(y, find(x));
    }
    reprs.insert(x);
    vector<int> deletes;
    for (auto y : reprs)
      if (y != find(y)) deletes.push_back(y);
    for (auto d : deletes) reprs.erase(d);
  }
  printf("%d\n", (int)reprs.size() - 1);
  return 0;
}
