#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const long long inf = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 5;
int tot, head[maxn];
struct E {
  int to, next;
} edge[maxn << 1];
void add(int u, int v) {
  edge[tot].to = v;
  edge[tot].next = head[u];
  head[u] = tot++;
}
int fa[maxn], n, m;
map<int, int> mp;
int sz[maxn];
int find(int x) {
  while (x != fa[x]) x = fa[x] = fa[fa[x]];
  return x;
}
void merge(int u, int v) {
  int eu = find(u), ev = find(v);
  if (eu == ev) return;
  fa[ev] = eu;
}
int main() {
  cin >> n >> m;
  memset(head, -1, sizeof(head));
  for (int i = 0; i <= n; i++) fa[i] = i;
  for (int i = 1; i <= m; i++) {
    int u, v;
    cin >> u >> v;
    add(u, v);
    add(v, u);
  }
  vector<int> g;
  for (int i = 1; i <= n; i++) {
    sz[i] = 1;
    mp.clear();
    for (int j = head[i]; j != -1; j = edge[j].next) {
      int v = edge[j].to;
      if (v >= i) continue;
      int ev = find(v);
      mp[ev]++;
    }
    for (int j = 0; j < g.size(); j++) {
      int s = find(g[j]);
      int t = find(i);
      if (s == t) continue;
      if (sz[s] > mp[s]) {
        int ei = find(i), es = find(s);
        fa[ei] = es;
        sz[es] += sz[ei];
      }
    }
    int fx = find(i);
    if (fx == i) g.push_back(fx);
  }
  int cnt = 0;
  for (int i = 1; i <= n; i++) {
    if (fa[i] == i) cnt++;
  }
  cout << cnt - 1 << '\n';
}
