#include <bits/stdc++.h>
using namespace std;
const long long mod = (long long)(1e9 + 7);
const long long inf = (long long)(2e9);
const long long linf = (long long)(4e18);
void solve();
signed main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  cout << fixed << setprecision(20);
  solve();
  return 0;
}
const long long N = (long long)(2 * 1e5 + 10);
long long p[N];
long long r[N];
long long clr[N];
void make_set(long long v) {
  p[v] = v;
  r[v] = 1;
}
long long find_set(long long v) {
  if (p[v] == v) return v;
  return p[v] = find_set(p[v]);
}
void union_sets(long long v, long long u) {
  v = find_set(v), u = find_set(u);
  if (v == u) return;
  if (r[v] < r[u]) swap(v, u);
  p[u] = v;
  r[v] += r[u];
  clr[u] = clr[v];
}
vector<set<long long>> g;
void solve() {
  long long n, m;
  cin >> n >> m;
  g.resize(n);
  for (auto i = 0; i < m; ++i) {
    long long v, u;
    cin >> v >> u;
    v--, u--;
    g[v].insert(u);
    g[u].insert(v);
  }
  for (auto i = 0; i < n; ++i) {
    make_set(i);
    clr[i] = i;
  }
  for (long long i = n - 1; i >= 0; --i) {
    if (r[find_set(i)] < n / 2 + 2) {
      for (auto j = 0; j < n; ++j) {
        if (g[i].count(j) == 0) union_sets(i, j);
      }
    }
  }
  vector<long long> ans;
  for (auto i = 0; i < n; ++i) {
    clr[i] = clr[find_set(i)];
  }
  sort(clr, clr + n);
  long long tmp = 1;
  for (auto i = 1; i < n; ++i) {
    if (clr[i] != clr[i - 1]) {
      ans.push_back(tmp);
      tmp = 1;
    } else
      tmp++;
  }
  ans.push_back(tmp);
  cout << (long long)(ans.size()) - 1 << "\n";
}
