//Created By:Hardik Kapoor
#include<bits/stdc++.h>

using namespace std;
//template begins
#define int long long int
#define ios ios_base::sync_with_stdio(false);cin.tie(NULL);
#define itt vector<int>:: iterator
#define pb push_back
#define mp make_pair
#define max3(a,b,c) max(max((a),(b)),(c))
#define max4(a,b,c,d) max(max((a),(b)),max((c),(d)))
#define min3(a,b,c) min(min((a),(b)),(c))
#define min4(a,b,c,d) min(min((a),(b)),min((c),(d)))
#define lb lower_bound
#define ub upper_bound
#define all(v) v.begin(),v.end()
#define db long double
#define itp vector<pair<int,int> >:: iterator
#define ff first
#define ss second
#define endl "\n"
typedef pair<int,int> pii;
const int inf=1000000000000000000;
const long double pi = 3.14159265358979323846264338;
const long long mod = 1000000007;
// const long long mod = 998244353;

int pow(int x, unsigned int y, int p){
    int res=1;
    x=x%p;
    if (x==0) return 0;
    while (y > 0)
    {
        if (y & 1)
            res = (res*x) % p;
        y = y>>1;
        x = (x*x) % p;
    }
    return res;
}
int invmod(int a,int m){
	return pow(a,m-2,m);
}
//template ends
const int maxn=1e5+5;
vector<int> par(maxn),si(maxn),adj[maxn];
set<int> make;

void make_set(int a)
{
	par[a]=a;
	si[a]=1;
	make.insert(a);
}

int find_set(int a)
{
	if(par[a]==a)
		return a;
	return par[a]=find_set(par[a]);
}

void union_set(int a,int b)
{
	a=find_set(a);
	b=find_set(b);
	if(a!=b)
	{
		if(si[a]<si[b])
			swap(a,b);
		par[b]=a;
		si[a]+=si[b];
		make.erase(b);
	}
}

signed main()
{
	ios
	int n,m;
	cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		int x,y;
		cin>>x>>y;
		adj[x].pb(y);
		adj[y].pb(x);
	}
	for(int i=1;i<=n;i++)
	{
		make_set(i);
		map<int,int> mz;
		for(int x:adj[i])
		{
			if(x<i)
				mz[find_set(x)]++;
		}
		set<int> temp=make;
		for(int y:temp)
		{
			if(y!=i)
				if(mz[find_set(y)]<si[find_set(y)])
					union_set(y,i);
		}
		make=temp;
	}
	int ans=(int)make.size()-1;
	cout<<ans<<endl;
}


//Created By:Hardik Kapoor
#include<bits/stdc++.h>

using namespace std;
//template begins
#define int long long int
#define ios ios_base::sync_with_stdio(false);cin.tie(NULL);
#define itt vector<int>:: iterator
#define pb push_back
#define mp make_pair
#define max3(a,b,c) max(max((a),(b)),(c))
#define max4(a,b,c,d) max(max((a),(b)),max((c),(d)))
#define min3(a,b,c) min(min((a),(b)),(c))
#define min4(a,b,c,d) min(min((a),(b)),min((c),(d)))
#define lb lower_bound
#define ub upper_bound
#define all(v) v.begin(),v.end()
#define db long double
#define itp vector<pair<int,int> >:: iterator
#define ff first
#define ss second
#define endl "\n"
typedef pair<int,int> pii;
const int inf=1000000000000000000;
const long double pi = 3.14159265358979323846264338;
const long long mod = 1000000007;
// const long long mod = 998244353;

int pow(int x, unsigned int y, int p){
    int res=1;
    x=x%p;
    if (x==0) return 0;
    while (y > 0)
    {
        if (y & 1)
            res = (res*x) % p;
        y = y>>1;
        x = (x*x) % p;
    }
    return res;
}
int invmod(int a,int m){
	return pow(a,m-2,m);
}
//template ends
const int maxn=1e5+5;
vector<int> adj[maxn],par(maxn),size(maxn);
set<int> ma;

void make_set(int a)
{
	ma.insert(a);
	par[a]=a;
	size[a]=1;
}

int find_set(int a)
{
	if(par[a]==a)
		return a;
	return par[a]=find_set(par[a]);
}

void union_set(int a,int b)
{
	a=find_set(a);
	b=find_set(b);
	if(a!=b)
	{
		if(size[a]<size[b])
			swap(a,b);
		par[b]=a;
		size[a]+=size[b];
		ma.erase(b);
	}
}

signed main(){
	ios
	int n,m;
	cin>>n>>m;
	for(int i=0,x,y;i<m;i++)
	{
		cin>>x>>y;
		adj[x].pb(y);
		adj[y].pb(x);
	}
	for(int i=1;i<=n;i++)
	{
		make_set(i);
		map<int,int> m;
		for(int x:adj[i])
		{
			if(x<i)
				m[find_set(x)]++;
		}
		for(int y:ma)
		{
			if(m[y]<size[y])
			{
				union_set(y,i);
			}
		}
	}
	cout<<ma.size()-1<<endl;
}


//Created By:Hardik Kapoor
#include<bits/stdc++.h>

using namespace std;
//template begins
#define int long long int
#define ios ios_base::sync_with_stdio(false);cin.tie(NULL);
#define itt vector<int>:: iterator
#define pb push_back
#define mp make_pair
#define max3(a,b,c) max(max((a),(b)),(c))
#define max4(a,b,c,d) max(max((a),(b)),max((c),(d)))
#define min3(a,b,c) min(min((a),(b)),(c))
#define min4(a,b,c,d) min(min((a),(b)),min((c),(d)))
#define lb lower_bound
#define ub upper_bound
#define all(v) v.begin(),v.end()
#define db long double
#define itp vector<pair<int,int> >:: iterator
#define ff first
#define ss second
#define endl "\n"
typedef pair<int,int> pii;
const int inf=1000000000000000000;
const long double pi = 3.14159265358979323846264338;
const long long mod = 1000000007;
// const long long mod = 998244353;

int pow(int x, unsigned int y, int p){
    int res=1;
    x=x%p;
    if (x==0) return 0;
    while (y > 0)
    {
        if (y & 1)
            res = (res*x) % p;
        y = y>>1;
        x = (x*x) % p;
    }
    return res;
}
int invmod(int a,int m){
	return pow(a,m-2,m);
}
//template ends
const int maxn=1e5+5;
vector<int> tadj[maxn],rec(maxn),vis(maxn);
int cnt=0;

void dfs(int st,int prev)
{
	vis[st]=1;
	rec[st]=1;
	for(int i:tadj[st])
	{
		if(i==prev)
			continue;
		if(!vis[i])
			dfs(i,st);
		if(rec[i])
			cnt++;
	}
	rec[st]=0;
}

signed main(){
	ios
	int n,m;
	cin>>n>>m;
	vector<int> adj[n+1];
	for(int i=0,x,y;i<m;i++)
	{
		cin>>x>>y;
		adj[x].pb(y);
		adj[y].pb(x);
	}
	int z=(n*(n-1))/2;
	if((z-m)>=(n-1))
	{
		cout<<0<<endl;
	}
	else{
	//	cout<<endl;
		for(int i=1;i<=n;i++)
		{
			set<int> s;
			for(int j:adj[i])
			{
				s.insert(j);
			}
			for(int l=i+1;l<=n;l++)
			{
				if(!s.count(l))
				{
					tadj[i].pb(l);
					tadj[l].pb(i);
			//		cout<<i<<" "<<l<<endl;
				}
			}
		}
		for(int i=1;i<=n;i++)
		{
			if(!vis[i])
			{
				dfs(i,0);
			}
		//	cout<<i<<" "<<cnt<<endl;
		}
		cout<<(n-1)-(z-m-cnt)<<endl;
	}
}


//Created By:Hardik Kapoor
#include<bits/stdc++.h>

using namespace std;
//template begins
#define int long long int
#define ios ios_base::sync_with_stdio(false);cin.tie(NULL);
#define itt vector<int>:: iterator
#define pb push_back
#define mp make_pair
#define max3(a,b,c) max(max((a),(b)),(c))
#define max4(a,b,c,d) max(max((a),(b)),max((c),(d)))
#define min3(a,b,c) min(min((a),(b)),(c))
#define min4(a,b,c,d) min(min((a),(b)),min((c),(d)))
#define lb lower_bound
#define ub upper_bound
#define all(v) v.begin(),v.end()
#define db long double
#define itp vector<pair<int,int> >:: iterator
#define ff first
#define ss second
#define endl "\n"
typedef pair<int,int> pii;
const int inf=1000000000000000000;
const long double pi = 3.14159265358979323846264338;
const long long mod = 1000000007;
// const long long mod = 998244353;

int pow(int x, unsigned int y, int p){
    int res=1;
    x=x%p;
    if (x==0) return 0;
    while (y > 0)
    {
        if (y & 1)
            res = (res*x) % p;
        y = y>>1;
        x = (x*x) % p;
    }
    return res;
}
int invmod(int a,int m){
	return pow(a,m-2,m);
}
//template ends
const int maxn=1e5+5;
vector<int> tadj[maxn],rec(maxn),vis(maxn);
int cnt=0;

void dfs(int st,int prev)
{
	vis[st]=1;
	rec[st]=1;
	for(int i:tadj[st])
	{
		if(i==prev)
			continue;
		if(!vis[i])
			dfs(i,st);
		if(rec[i])
			cnt++;
	}
	rec[st]=0;
}

signed main(){
	ios
	int n,m;
	cin>>n>>m;
	vector<int> adj[n+1];
	for(int i=0,x,y;i<m;i++)
	{
		cin>>x>>y;
		adj[x].pb(y);
		adj[y].pb(x);
	}
	int z=(n*(n-1))/2;
	if((z-m)>3*(n-1))
	{
		cout<<0<<endl;
	}
	else{
	//	cout<<endl;
		for(int i=1;i<=n;i++)
		{
			set<int> s;
			for(int j:adj[i])
			{
				s.insert(j);
			}
			for(int l=i+1;l<=n;l++)
			{
				if(!s.count(l))
				{
					tadj[i].pb(l);
					tadj[l].pb(i);
			//		cout<<i<<" "<<l<<endl;
				}
			}
		}
		for(int i=1;i<=n;i++)
		{
			if(!vis[i])
			{
				dfs(i,0);
			}
		//	cout<<i<<" "<<cnt<<endl;
		}
		cout<<(n-1)-(z-m-cnt)<<endl;
	}
}


//Created By:Hardik Kapoor
#include<bits/stdc++.h>

using namespace std;
//template begins
#define int long long int
#define ios ios_base::sync_with_stdio(false);cin.tie(NULL);
#define itt vector<int>:: iterator
#define pb push_back
#define mp make_pair
#define max3(a,b,c) max(max((a),(b)),(c))
#define max4(a,b,c,d) max(max((a),(b)),max((c),(d)))
#define min3(a,b,c) min(min((a),(b)),(c))
#define min4(a,b,c,d) min(min((a),(b)),min((c),(d)))
#define lb lower_bound
#define ub upper_bound
#define all(v) v.begin(),v.end()
#define db long double
#define itp vector<pair<int,int> >:: iterator
#define ff first
#define ss second
#define endl "\n"
typedef pair<int,int> pii;
const int inf=1000000000000000000;
const long double pi = 3.14159265358979323846264338;
const long long mod = 1000000007;
// const long long mod = 998244353;

int pow(int x, unsigned int y, int p){
    int res=1;
    x=x%p;
    if (x==0) return 0;
    while (y > 0)
    {
        if (y & 1)
            res = (res*x) % p;
        y = y>>1;
        x = (x*x) % p;
    }
    return res;
}
int invmod(int a,int m){
	return pow(a,m-2,m);
}
//template ends
const int maxn=1e5+5;
vector<int> tadj[maxn],rec(maxn),vis(maxn);
int cnt=0;

void dfs(int st,int prev)
{
	vis[st]=1;
	rec[st]=1;
	for(int i:tadj[st])
	{
		if(i==prev)
			continue;
		if(!vis[i])
			dfs(i,st);
		if(rec[i])
			cnt++;
	}
	rec[st]=0;
}

signed main(){
	ios
	int n,m;
	cin>>n>>m;
	vector<int> adj[n+1];
	for(int i=0,x,y;i<m;i++)
	{
		cin>>x>>y;
		adj[x].pb(y);
		adj[y].pb(x);
	}
	int z=(n*(n-1))/2;
	if((z-m)>(n-1))
	{
		cout<<0<<endl;
	}
	else{
	//	cout<<endl;
		for(int i=1;i<=n;i++)
		{
			set<int> s;
			for(int j:adj[i])
			{
				s.insert(j);
			}
			for(int l=i+1;l<=n;l++)
			{
				if(!s.count(l))
				{
					tadj[i].pb(l);
					tadj[l].pb(i);
			//		cout<<i<<" "<<l<<endl;
				}
			}
		}
		for(int i=1;i<=n;i++)
		{
			if(!vis[i])
			{
				dfs(i,0);
			}
		//	cout<<i<<" "<<cnt<<endl;
		}
		cout<<(n-1)-(z-m-cnt)<<endl;
	}
}


//Created By:Hardik Kapoor
#include<bits/stdc++.h>

using namespace std;
//template begins
#define int long long int
#define ios ios_base::sync_with_stdio(false);cin.tie(NULL);
#define itt vector<int>:: iterator
#define pb push_back
#define mp make_pair
#define max3(a,b,c) max(max((a),(b)),(c))
#define max4(a,b,c,d) max(max((a),(b)),max((c),(d)))
#define min3(a,b,c) min(min((a),(b)),(c))
#define min4(a,b,c,d) min(min((a),(b)),min((c),(d)))
#define lb lower_bound
#define ub upper_bound
#define all(v) v.begin(),v.end()
#define db long double
#define itp vector<pair<int,int> >:: iterator
#define ff first
#define ss second
#define endl "\n"
typedef pair<int,int> pii;
const int inf=1000000000000000000;
const long double pi = 3.14159265358979323846264338;
const long long mod = 1000000007;
// const long long mod = 998244353;

int pow(int x, unsigned int y, int p){
    int res=1;
    x=x%p;
    if (x==0) return 0;
    while (y > 0)
    {
        if (y & 1)
            res = (res*x) % p;
        y = y>>1;
        x = (x*x) % p;
    }
    return res;
}
int invmod(int a,int m){
	return pow(a,m-2,m);
}
//template ends
const int maxn=1e5+5;
vector<int> adj[maxn],par(maxn),si(maxn);
set<int> ma;

void make_set(int a)
{
	ma.insert(a);
	par[a]=a;
	si[a]=1;
}

int find_set(int a)
{
	if(par[a]==a)
		return a;
	return par[a]=find_set(par[a]);
}

void union_set(int a,int b)
{
	a=find_set(a);
	b=find_set(b);
	if(a!=b)
	{
		if(si[a]<si[b])
			swap(a,b);
		par[b]=a;
		si[a]+=si[b];
		ma.erase(b);
	}
}

signed main(){
	ios
	int n,m;
	cin>>n>>m;
	for(int i=0,x,y;i<m;i++)
	{
		cin>>x>>y;
		adj[x].pb(y);
		adj[y].pb(x);
	}
	for(int i=1;i<=n;i++)
	{
		make_set(i);
		map<int,int> m;
		for(int x:adj[i])
		{
			if(x<i)
				m[find_set(x)]++;
		}
		for(int y:ma)
		{
			if(m.find(y)==m.end())
				union_set(y,i);
			else if(m[y]<si[y])
			{
				union_set(y,i);
			}
		}
	}
	cout<<ma.size()-1<<endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m,ans=-1;
vector<priority_queue<ll> > g;
vector<bool> used;
void dfs(ll v)
{
    used[v]=true;
    //vector<ll> col(n+1,0);
    for(ll i=n;i>=1;i--)
    {
        if(!g[v].empty()){
        if(g[v].top()==i) {g[v].pop();continue;}}
        if(used[i]) continue;
        dfs(i);
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin>>n>>m;
    if(m==0||n==1) {cout<<0;return 0;}
    g.resize(n+1);
    used.resize(n+1,false);
    for(ll i=1;i<=m;i++)
    {
        ll a,b;cin>>a>>b;
        g[a].push(b);
        g[b].push(a);
    }
    //while(1==1)
    //{
      //  ll v;
        for(int i=1;i<=n;i++)
        {
            if(used[i]) {continue;}
            ans++;
            dfs(i);
        }
    //}
    cout<<ans;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef int ll;
ll n,m;
set<ll> vse;
vector<set<ll> > g;
vector<bool> used;
void bfs(ll v)
{
    queue <ll> q;
    q.push(v);
    vse.erase(v);
    used[v]=true;
    while(!q.empty())
    {
        ll x=q.front();
        q.pop();
        for(auto it=vse.begin();it!=vse.end();/*it++*/)
        {
            ll y=*it++;
            if(g[x].count(y)==0)
            {
                used[y]=true;
                q.push(y);
                vse.erase(y);
            }
        }
    }

}

int main()
{
    ios_base::sync_with_stdio(false);
    cin>>n>>m;
    g.resize(n+1);
    used.resize(n+1,false);
    for(int i=1;i<=n;i++) vse.insert(i);
    for(int i=1;i<=m;i++)
    {
        ll a,b;cin>>a>>b;
        g[a].insert(b);
        g[b].insert(a);
    }//cout<<"ISTUPID ";
    ll ans=-1;
    for(int i=1;i<=n;i++)
    {
        if(!used[i])
        {
            ans++;
            bfs(i);
        }
    }
    cout<<ans;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef int ll;
ll n,m;
set<ll> vse;
vector<set<ll> > g;
vector<bool> used;
void bfs(ll v)
{
    queue <ll> q;
    q.push(v);
    vse.erase(v);
    used[v]=true;
    while(!q.empty())
    {
        ll x=q.front();
        q.pop();
        for(auto it=vse.begin();it!=vse.end();it++)
        {
            ll y=*it;

            if(g[x].count(y)==0)
            {
                //dddddddddddddd
                used[y]=true;
                q.push(y);
                vse.erase(y);
            }
        }
    }

}

int main()
{
    ios_base::sync_with_stdio(false);
    cin>>n>>m;
    g.resize(n+1);
    used.resize(n+1,false);
    for(int i=1;i<=n;i++) vse.insert(i);
    for(int i=1;i<=m;i++)
    {
        ll a,b;cin>>a>>b;
        g[a].insert(b);
        g[b].insert(a);
    }//cout<<"ISTUPID ";
    ll ans=-1;
    for(int i=1;i<=n;i++)
    {
        if(!used[i])
        {
            ans++;
            bfs(i);
        }
    }
    cout<<ans;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef int ll;
ll n,m;
set<ll> vse;
vector<set<ll> > g;
vector<bool> used;
void bfs(ll v)
{
    queue <ll> q;
    q.push(v);
    vse.erase(v);
    used[v]=true;
    while(!q.empty())
    {
        ll x=q.front();
        q.pop();
        for(auto it=vse.begin();it!=vse.end();)
        {
            ll y=*it;
            if(g[x].count(y)==0)
            {
                used[y]=true;
                q.push(y);
                vse.erase(y);
            }
        }
    }

}

int main()
{
    ios_base::sync_with_stdio(false);
    cin>>n>>m;
    g.resize(n+1);
    used.resize(n+1,false);
    //for(int i=1;i<=n;i++) vse.insert(i);
    for(int i=1;i<=m;i++)
    {
        ll a,b;cin>>a>>b;
        g[a].insert(b);
        g[b].insert(a);
    }cout<<"ISTUPID ";
    ll ans=-1;
    for(int i=1;i<=n;i++)
    {
        if(!used[i])
        {
            ans++;
            bfs(i);
        }
    }
    cout<<ans;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m,ans=-1;
vector<priority_queue<ll> > g;
vector<bool> used;
void dfs(ll v)
{
    used[v]=true;
    //vector<ll> col(n+1,0);
    for(ll i=n;i>=1;i--)
    {
        if(g[v].top()==i) {g[v].pop();continue;}
        if(used[i]) continue;
        dfs(i);
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin>>n>>m;
    if(m==0||n==1) {cout<<0;return 0;}
    g.resize(n+1);
    used.resize(n+1,false);
    for(ll i=1;i<=m;i++)
    {
        ll a,b;cin>>a>>b;
        g[a].push(b);
        g[b].push(a);
    }
    //while(1==1)
    //{
      //  ll v;
        for(int i=1;i<=n;i++)
        {
            if(used[i]) {continue;}
            ans++;
            dfs(i);
        }
    //}
    cout<<ans;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef int ll;
ll n,m;
set<ll> vse;
vector<set<ll> > g;
vector<bool> used;
void bfs(ll v)
{
    queue <ll> q;
    q.push(v);
    vse.erase(v);
    used[v]=true;
    while(!q.empty())
    {
        ll x=q.front();
        q.pop();
        for(auto it=vse.begin();it!=vse.end();it++)
        {
            ll y=*it;

            if(g[x].count(y)==0&&used[y]==false)
            {
                used[y]=true;
                q.push(y);
                vse.erase(y);
            }
        }
    }

}

int main()
{
    ios_base::sync_with_stdio(false);
    cin>>n>>m;
    g.resize(n+1);
    used.resize(n+1,false);
    for(int i=1;i<=n;i++) vse.insert(i);
    for(int i=1;i<=m;i++)
    {
        ll a,b;cin>>a>>b;
        g[a].insert(b);
        g[b].insert(a);
    }//cout<<"ISTUPID ";
    ll ans=-1;
    for(int i=1;i<=n;i++)
    {
        if(!used[i])
        {
            ans++;
            bfs(i);
        }
    }
    cout<<ans;

    return 0;
}


    #include <bits/stdc++.h>
    using namespace std;
    typedef int ll;
    ll n,m;
    set<ll> vse;
    vector<set<ll> > g;
    vector<bool> used;
    void bfs(ll v)
    {
        queue <ll> q;
        q.push(v);
        vse.erase(v);
        used[v]=true;
        while(!q.empty())
        {
            ll x=q.front();
            q.pop();
            for(auto it=vse.begin();it!=vse.end();it++)
            {
                ll y=*it;
                if(g[x].count(y)==0)
                {
                    used[y]=true;
                    q.push(y);
                    vse.erase(y);
                }
            }
        }

    }
     //asdasfasdf
    int main()
    {
        ios_base::sync_with_stdio(false);
        cin>>n>>m;
        g.resize(n+1);
        used.resize(n+1,false);
        for(int i=1;i<=n;i++) vse.insert(i);
        for(int i=1;i<=m;i++)
        {
            ll a,b;cin>>a>>b;
            g[a].insert(b);
            g[b].insert(a);
        }//cout<<"ISTUPID ";
        ll ans=-1;
        for(int i=1;i<=n;i++)
        {
            if(!used[i])
            {
                ans++;
                bfs(i);
            }
        }
        cout<<ans;

        return 0;
    }


#include <bits/stdc++.h>
using namespace std;
typedef int ll;
ll n,m;
set<ll> vse;
vector<set<ll> > g;
vector<bool> used;
void bfs(ll v)
{
    queue <ll> q;
    q.push(v);
    vse.erase(v);
    used[v]=true;
    while(!q.empty())
    {
        ll x=q.front();
        q.pop();
        for(auto it=vse.begin();it!=vse.end();)
        {
            ll y=*it;
            if(g[x].count(y)==0)
            {
                used[y]=true;
                q.push(y);
                vse.erase(y);
            }
        }
    }

}

int main()
{
    ios_base::sync_with_stdio(false);
    cin>>n>>m;
    g.resize(n+1);
    used.resize(n+1,false);
    for(int i=1;i<=2;i++) vse.insert(i);
    for(int i=1;i<=m;i++)
    {
        ll a,b;cin>>a>>b;
        g[a].insert(b);
        g[b].insert(a);
    }cout<<"ISTUPID ";
    ll ans=-1;
    for(int i=1;i<=n;i++)
    {
        if(!used[i])
        {
            ans++;
            bfs(i);
        }
    }
    cout<<ans;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef int ll;
ll n,m;
set<ll> vse;
vector<set<ll> > g;
vector<bool> used;
void bfs(ll v)
{
    queue <ll> q;
    q.push(v);
    vse.erase(v);
    used[v]=true;
    while(!q.empty())
    {
        ll x=q.front();
        q.pop();
        for(auto it=vse.begin();it!=vse.end();)
        {
            ll y=*it;
            if(g[x].count(y)==0)
            {
                used[y]=true;
                q.push(y);
                vse.erase(y);
            }
        }
    }

}

int main()
{
    ios_base::sync_with_stdio(false);
    cin>>n>>m;
    g.resize(n+1);
    used.resize(n+1,false);
    for(int i=1;i<=n;i++) vse.insert(i);
    for(int i=1;i<=m;i++)
    {
        ll a,b;cin>>a>>b;
        g[a].insert(b);
        g[b].insert(a);
    }cout<<"ISTUPID ";
    ll ans=-1;
    for(int i=1;i<=n;i++)
    {
        if(!used[i])
        {
            ans++;
            bfs(i);
        }
    }
    cout<<ans;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef int ll;
ll n,m;
set<ll> vse;
vector<set<ll> > g;
vector<bool> used;
void bfs(ll v)
{
    queue <ll> q;
    q.push(v);
    vse.erase(v);
    used[v]=true;
    while(!q.empty())
    {
        ll x=q.front();
        q.pop();
        for(auto it=vse.begin();it!=vse.end();it++)
        {
            ll y=*it;
            if(g[x].count(y)==0)
            {
                used[y]=true;
                q.push(y);
                vse.erase(y);
            }
        }
    }

}

int main()
{
    ios_base::sync_with_stdio(false);
    cin>>n>>m;
    g.resize(n+1);
    used.resize(n+1,false);
    for(int i=1;i<=n;i++) vse.insert(i);
    for(int i=1;i<=m;i++)
    {
        ll a,b;cin>>a>>b;
        g[a].insert(b);
        g[b].insert(a);
    }//cout<<"ISTUPID ";
    ll ans=-1;
    for(int i=1;i<=n;i++)
    {
        if(!used[i])
        {
            ans++;
            bfs(i);
        }
    }
    cout<<ans;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef int ll;
ll n,m;
set<ll> vse;
vector<set<ll> > g;
vector<bool> used;
void bfs(ll v)
{
    queue <ll> q;
    q.push(v);
    vse.erase(v);
    used[v]=true;
    while(!q.empty())
    {
        ll x=q.front();
        q.pop();
        for(auto it=vse.begin();it!=vse.end();it++)
        {
            ll y=*it;

            if(g[x].count(y)==0&&vse.count(y)>0)
            {
                used[y]=true;
                q.push(y);
                vse.erase(y);
            }
        }
    }

}

int main()
{
    ios_base::sync_with_stdio(false);
    cin>>n>>m;
    g.resize(n+1);
    used.resize(n+1,false);
    for(int i=1;i<=n;i++) vse.insert(i);
    for(int i=1;i<=m;i++)
    {
        ll a,b;cin>>a>>b;
        g[a].insert(b);
        g[b].insert(a);
    }//cout<<"ISTUPID ";
    ll ans=-1;
    for(int i=1;i<=n;i++)
    {
        if(!used[i])
        {
            ans++;
            bfs(i);
        }
    }
    cout<<ans;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef int ll;
ll n,m;
set<ll> vse;
vector<set<ll> > g;
vector<bool> used;
void bfs(ll v)
{
    queue <ll> q;
    q.push(v);
    vse.erase(v);
    used[v]=true;
    while(!q.empty())
    {
        ll x=q.front();
        q.pop();
        for(auto it=vse.begin();it!=vse.end();)
        {
            ll y=*it;
            it++;
            if(g[x].count(y)==0)
            {
                used[y]=true;
                q.push(y);
                vse.erase(y);
            }
        }
    }

}

int main()
{
    ios_base::sync_with_stdio(false);
    cin>>n>>m;
    g.resize(n+1);
    used.resize(n+1,false);
    for(int i=1;i<=n;i++) vse.insert(i);
    for(int i=1;i<=m;i++)
    {
        ll a,b;cin>>a>>b;
        g[a].insert(b);
        g[b].insert(a);
    }//cout<<"ISTUPID ";
    ll ans=-1;
    for(int i=1;i<=n;i++)
    {
        if(!used[i])
        {
            ans++;
            bfs(i);
        }
    }
    cout<<ans;

    return 0;
}


#include <bits/stdc++.h>
#define simplify ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long
#define endl "\n"
using namespace std;

const int N=1e5+5;
set<int>neighbours[N];
int n,m;

int32_t main()
{
    simplify

    cin>>n>>m;
    int u,v;
    for(int i=0;i<m;i++){
        cin>>u>>v;
        u--;v--;
        neighbours[u].insert(v);
        neighbours[v].insert(u);
    }
    set<int>unvisited;
    for(int i=0;i<n;i++)unvisited.insert(i);
    int cost=n-1;

    for(int i=0;i<n;i++){
        if(unvisited.count(i)){
            unvisited.erase(i);
            set<int>component;
            component.insert(i);
            while(!component.empty()){
                int x=*component.begin();
                component.erase(x);
                set<int>toDelete;
                for(auto node:unvisited){
                    if(neighbours[x].count(node))continue;
                    component.insert(node);
                    toDelete.insert(node);
                    cost--;
                }
                for(auto node:toDelete)unvisited.erase(node);
            }
        }
    }
    cout<<cost;

    return 0;
}


#include <bits/stdc++.h>
#define simplify ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long
#define endl "\n"
using namespace std;

const int N=1e5+5;
set<int>neighbours[N];
set<int>unvisited;
int n,m;

void dfs(int u){
    unvisited.erase(u);
    vector<int>nextNodes;
    for(auto it:unvisited){
        if(neighbours[u].count(it))continue;
        nextNodes.push_back(it);
    }
    for(auto it:nextNodes){
        unvisited.erase(it);
    }
    for(auto it:nextNodes){
        dfs(it);
    }
}

int32_t main()
{
    simplify

    cin>>n>>m;
    int u,v;
    for(int i=0;i<m;i++){
        cin>>u>>v;
        u--;v--;
        neighbours[u].insert(v);
        neighbours[v].insert(u);
    }

    for(int i=0;i<n;i++)unvisited.insert(i);
    int cost=0;

    for(int i=0;i<n;i++){
        if(unvisited.count(i)){
            cost++;
            dfs(i);
        }
    }
    cout<<cost-1;

    return 0;
}


#include <bits/stdc++.h>
#define simplify ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long
#define endl "\n"
using namespace std;

const int N=1e5+5;
set<int>neighbours[N];
int n,m;

int32_t main()
{
    simplify

    cin>>n>>m;
    int u,v;
    for(int i=0;i<m;i++){
        cin>>u>>v;
        u--;v--;
        neighbours[u].insert(v);
        neighbours[v].insert(u);
    }
    set<int>unvisited;
    for(int i=0;i<n;i++)unvisited.insert(i);
    int currNode=0;
    int cost=0;
    unvisited.erase(0);
    for(int i=0;i<n;i++){
        bool allOnes=true;
        for(int j=0;j<n;j++){
            if(unvisited.count(j) && !neighbours[currNode].count(j)){
                unvisited.erase(j);
                currNode=j;
                allOnes=false;
                break;
            }
        }
        if(allOnes && i!=n-1){
            currNode=*unvisited.begin();
            cost+=1;
        }
    }
    cout<<cost;

    return 0;
}


#include <bits/stdc++.h>
#define simplify ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long
#define endl "\n"
using namespace std;

const int N=1e5+5;
set<int>neighbours[N];
int n,m;

int32_t main()
{
    simplify

    cin>>n>>m;
    int u,v;
    for(int i=0;i<m;i++){
        cin>>u>>v;
        u--;v--;
        neighbours[u].insert(v);
        neighbours[v].insert(u);
    }
    set<int>unvisited;
    for(int i=0;i<n;i++)unvisited.insert(i);
    int currNode=0;
    int cost=0;
    unvisited.erase(0);
    while(!unvisited.empty()){
        bool allOnes=true;
        for(auto j:unvisited){
            if(!neighbours[currNode].count(j)){
                unvisited.erase(j);
                currNode=j;
                allOnes=false;
                break;
            }
        }
        if(allOnes){
            if(unvisited.size()){
                currNode=*unvisited.begin();
                unvisited.erase(currNode);
            }
            cost+=1;
        }
    }
    cout<<cost;

    return 0;
}


#include <bits/stdc++.h>
#define simplify ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long
#define endl "\n"
using namespace std;

const int N=1e5+5;
set<int>neighbours[N];
int n,m;

int32_t main()
{
    simplify

    cin>>n>>m;
    int u,v;
    for(int i=0;i<m;i++){
        cin>>u>>v;
        u--;v--;
        neighbours[u].insert(v);
        neighbours[v].insert(u);
    }
    set<int>unvisited;
    for(int i=0;i<n;i++)unvisited.insert(i);
    int currNode=0;
    int cost=0;
    unvisited.erase(0);
    for(int i=0;i<n;i++){
        bool allOnes=true;
        for(int j=0;j<n;j++){
            if(unvisited.count(j) && !neighbours[currNode].count(j)){
                unvisited.erase(j);
                cout<<currNode<<"  Here"<<endl;
                currNode=j;
                allOnes=false;
                break;
            }
        }
        if(allOnes && i!=n-1){
            //cout<<currNode<<endl;
            currNode=*unvisited.begin();
            unvisited.erase(currNode);
            cost+=1;
        }
    }
    cout<<cost;

    return 0;
}


#include <bits/stdc++.h>
#define simplify ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long
#define endl "\n"
using namespace std;

const int N=1e5+5;
set<int>neighbours[N];
int n,m;

int32_t main()
{
    simplify

    cin>>n>>m;
    int u,v;
    for(int i=0;i<m;i++){
        cin>>u>>v;
        u--;v--;
        neighbours[u].insert(v);
        neighbours[v].insert(u);
    }
    set<int>unvisited;
    for(int i=0;i<n;i++)unvisited.insert(i);
    int currNode=0;
    int cost=0;
    unvisited.erase(0);
    for(int i=0;i<n;i++){
        bool allOnes=true;
        for(int j=0;j<n;j++){
            if(unvisited.count(j) && !neighbours[currNode].count(j)){
                unvisited.erase(j);
                currNode=j;
                allOnes=false;
                break;
            }
        }
        if(allOnes && i!=n-1){
            currNode=*unvisited.begin();
            unvisited.erase(currNode);
            cost+=1;
        }
    }
    cout<<cost;

    return 0;
}


#include <bits/stdc++.h>
#define simplify ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long
#define endl "\n"
using namespace std;

const int N=1e5+5;
set<int>neighbours[N];
int n,m;

int32_t main()
{
    simplify

    cin>>n>>m;
    int u,v;
    for(int i=0;i<m;i++){
        cin>>u>>v;
        u--;v--;
        neighbours[u].insert(v);
        neighbours[v].insert(u);
    }
    set<int>unvisited;
    for(int i=0;i<n;i++)unvisited.insert(i);
    int cost=n-1;

    for(int currNode=0;currNode<n;currNode++){
        if(!unvisited.count(currNode))continue;

            unvisited.erase(currNode);
            set<int>component;
            component.insert(currNode);
            //BFS from CurrNode to all the nodes with 0 wt
            while(!component.empty()){
                int x=*component.begin();
                component.erase(x);
                set<int>toDelete;
                for(auto node:unvisited){
                    if(neighbours[x].count(node))continue;
                    component.insert(node);
                    toDelete.insert(node);
                    cost--;
                }
                for(auto node:toDelete)unvisited.erase(node);
            }

    }
    cout<<cost;

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
unordered_set<long long int> graph;
unordered_set<int> se;
namespace IO{
	char ss[1<<17],*A=ss,*B=ss;
	inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	template<class T>inline void sd(T&x){
		char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45){y=-1;}x=c-48;
		while(c=gc(),47<c&&c<58){x=x*10+c-48;}x*=y;
	}
}
using namespace IO;
unordered_set<int>::iterator it,now;
int n,m,u,v,i,cnt=0,ft=0,rr=0;
int q[100005];
void bfs() {
	q[rr++]=*now;
	se.erase(*now);
	while(rr-ft){
		u=q[ft++];
		for(it=se.begin();it!=se.end();){
			v=*it++;
			if(!graph.count(u<v?v*1000000+u:u*1000000+v)){
				q[rr++]=v,se.erase(v);
			}
		}
	}
	now=se.begin();
}
int main(){
	sd(n),sd(m);
	for(i=0;i<m;i++){
		sd(u),sd(v);
		graph.insert(u<v?v*1000000+u:u*1000000+v);
	}
	for(i=1;i<=n;i++)se.insert(i);
	now=se.begin();
	while(now!=se.end()){
		bfs();
		cnt++;
	}
	printf("%d\n",cnt-1);
}


#include<bits/stdc++.h>
using namespace std;
unordered_set<long long int> graph;
unordered_set<int> se;
namespace IO{
	char ss[1<<17],*A=ss,*B=ss;
	inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	template<class T>inline void sd(T&x){
		char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45){y=-1;}x=c-48;
		while(c=gc(),47<c&&c<58){x=x*10+c-48;}x*=y;
	}
}
using namespace IO;
unordered_set<int>::iterator bfs(int u) {
	queue<int> q;
	q.push(u);
	int v;
	while(q.size()){
		u=q.front();
		q.pop();
		for(unordered_set<int>::iterator it=se.begin();it!=se.end();){
			v=*it++;
			if(!graph.count(min(u,v)*1000000+max(u,v)))
				q.push(v),se.erase(v);
		}
	}
	return se.begin();
}
int main(){
	int n,m,a,b,cnt=0;
	sd(n),sd(m);
	for(int i=0;i<m;i++){
		sd(a),sd(b);
		graph.insert(min(a,b)*1000000+max(a,b));
	}
	for(int i=1;i<=n;i++)se.insert(i);
	unordered_set<int>::iterator now=se.begin();
	while((now=bfs(*now))!=se.end()){
		cnt++;
	}
	printf("%d\n",cnt);
}


#include<bits/stdc++.h>
using namespace std;
unordered_set<int> graph[100005];
unordered_set<int> se;
void bfs(int u) {
	queue<int> q;
	q.push(u);
	while(q.size()){
		u=q.front();
		q.pop();
		for(auto it=se.begin();it!=se.end();){
			int v=*it++;
			if(!graph[u].count(v))
				q.push(v),se.erase(v);
		}
	}
}
int main(){
	int n,m,a,b,cnt=0;
	scanf("%d %d",&n,&m);
	for(int i=0;i<m;i++){
		scanf("%d %d",&a,&b);
		graph[a].insert(b);
		graph[b].insert(a);
	}
	for(int i=1;i<=n;i++)se.insert(i);
	for(int i=1;i<=n;i++){
		if(se.count(i)){
			bfs(i);
			cnt++;
		}
	}
	printf("%d\n",cnt-1);
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
unordered_set<ll> mape;
vector<ll> graph[100005];
vector<pll> edge;
set<vector<ll> > ans;
int main(){
	ll n,m;
	cin>>n>>m;
	ll a,b;
	for(int i=0;i<m;i++){
		cin>>a>>b;
		edge.push_back({a,b});
		edge.push_back({b,a});
		mape.insert(a*1000000+b);
		mape.insert(b*1000000+a);
		graph[a].push_back(b);
		graph[b].push_back(a);
	}
	for(int i=0;i<m*2;i++){
		pll e = edge[i];
		vector<ll> vec;
		for(auto it:graph[e.first]){
			if(mape.count(it*1000000+e.second)){
				vec.push_back(it);
				//cout<<e.first<<" "<<e.second<<" "<<it<<endl;
			}
		}
		if(vec.size()){
			sort(vec.begin(),vec.end());
			ans.insert(vec);
		}
	}
	if(ans.size())
		cout<<ans.size()-1<<endl;
	else if(n==2&&m==1)
		cout<<1<<endl;
	else
		cout<<0<<endl;
}


#include<bits/stdc++.h>
using namespace std;
unordered_set<int> graph[100005];
unordered_set<int> se;
namespace IO{
	char ss[1<<17],*A=ss,*B=ss;
	inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	template<class T>inline void sd(T&x){
		char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45){y=-1;}x=c-48;
		while(c=gc(),47<c&&c<58){x=x*10+c-48;}x*=y;
	}
}
using namespace IO;
unordered_set<int>::iterator bfs(int u) {
	queue<int> q;
	q.push(u);
	while(q.size()){
		u=q.front();
		q.pop();
		for(unordered_set<int>::iterator it=se.begin();it!=se.end();){
			int v=*it++;
			if(!graph[u].count(v))
				q.push(v),se.erase(v);
		}
	}
	return se.begin();
}
int main(){
	int n,m,a,b,cnt=0;
	sd(n),sd(m);
	for(int i=0;i<m;i++){
		sd(a),sd(b);
		graph[a].insert(b);
		graph[b].insert(a);
	}
	for(int i=1;i<=n;i++)se.insert(i);
	unordered_set<int>::iterator now=se.begin();
	while((now=bfs(*now))!=se.end()){
		cnt++;
	}
	printf("%d\n",cnt);
}


#include<bits/stdc++.h>
using namespace std;
unordered_set<long long int> graph;
unordered_set<int> se;
namespace IO{
	char ss[1<<17],*A=ss,*B=ss;
	inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	template<class T>inline void sd(T&x){
		char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45){y=-1;}x=c-48;
		while(c=gc(),47<c&&c<58){x=x*10+c-48;}x*=y;
	}
}
using namespace IO;
unordered_set<int>::iterator it;
int n,m,a,b,v,i,cnt=0;
queue<int> q;
unordered_set<int>::iterator bfs(int u) {
	q.push(u);
	while(q.size()){
		u=q.front();
		q.pop();
		for(it=se.begin();it!=se.end();){
			v=*it++;
			if(!graph.count(min(u,v)*1000000+max(u,v)))
				q.push(v),se.erase(v);
		}
	}
	return se.begin();
}
int main(){
	sd(n),sd(m);
	for(i=0;i<m;i++){
		sd(a),sd(b);
		graph.insert(min(a,b)*1000000+max(a,b));
	}
	for(i=1;i<=n;i++)se.insert(i);
	unordered_set<int>::iterator now=se.begin();
	while((now=bfs(*now))!=se.end()){
		cnt++;
	}
	printf("%d\n",cnt);
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
unordered_set<ll> graph[100005];
unordered_set<ll> se;
void dfs(int u){
	vector<ll> era;
	era.clear();
	for(ll v:se)
		if(!graph[u].count(v))
			era.push_back(v);
	for(ll v:era)
		se.erase(v);
	for(ll v:era)
		dfs(v);
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie();
	ll n,m;
	cin>>n>>m;
	ll a,b;
	for(int i=0;i<m;i++){
		cin>>a>>b;
		graph[a].insert(b);
		graph[b].insert(a);
	}
	for(int i=1;i<=n;i++)se.insert(i);
	int cnt=0;
	for(int i=1;i<=n;i++){
		if(se.count(i)){
			dfs(i);
			cnt++;
		}
	}
	cout<<cnt-1<<endl;
}


#include<bits/stdc++.h>
using namespace std;
unordered_set<long long int> graph;
unordered_set<int> se;
namespace IO{
	char ss[1<<17],*A=ss,*B=ss;
	inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	template<class T>inline void sd(T&x){
		char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45){y=-1;}x=c-48;
		while(c=gc(),47<c&&c<58){x=x*10+c-48;}x*=y;
	}
}
using namespace IO;
unordered_set<int>::iterator it;
int n,m,u,v,i,cnt=0;
unordered_set<int>::iterator now;
queue<int> q;
unordered_set<int>::iterator bfs() {
	q.push(*now);
	while(q.size()){
		u=q.front();
		q.pop();
		for(it=se.begin();it!=se.end();){
			v=*it++;
			if(!graph.count(u<v?v*1000000+u:u*1000000+v))
				q.push(v),se.erase(v);
		}
	}
	return se.begin();
}
int main(){
	sd(n),sd(m);
	for(i=0;i<m;i++){
		sd(u),sd(v);
		graph.insert(u<v?v*1000000+u:u*1000000+v);
	}
	for(i=1;i<=n;i++)se.insert(i);
	now=se.begin();
	while((now=bfs())!=se.end()){
		cnt++;
	}
	printf("%d\n",cnt);
}


#include<bits/stdc++.h>
using namespace std;
unordered_set<int> graph;
unordered_set<int> se;
namespace IO{
	char ss[1<<17],*A=ss,*B=ss;
	inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	template<class T>inline void sd(T&x){
		char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45){y=-1;}x=c-48;
		while(c=gc(),47<c&&c<58){x=x*10+c-48;}x*=y;
	}
}
using namespace IO;
unordered_set<int>::iterator it;
int n,m,a,b,v,i,cnt=0;
queue<int> q;
unordered_set<int>::iterator bfs(int u) {
	q.push(u);
	while(q.size()){
		u=q.front();
		q.pop();
		for(it=se.begin();it!=se.end();){
			v=*it++;
			if(!graph.count(min(u,v)*100000+max(u,v)))
				q.push(v),se.erase(v);
		}
	}
	return se.begin();
}
int main(){
	sd(n),sd(m);
	for(i=0;i<m;i++){
		sd(a),sd(b);
		graph.insert(min(a,b)*100000+max(a,b));
	}
	for(i=1;i<=n;i++)se.insert(i);
	unordered_set<int>::iterator now=se.begin();
	while((now=bfs(*now))!=se.end()){
		cnt++;
	}
	printf("%d\n",cnt);
}


#include<bits/stdc++.h>
using namespace std;
unordered_set<int> graph[100005];
unordered_set<int> se;
void dfs(int u){
	vector<int> era;
	for(int v:se)
		if(!graph[u].count(v))
			era.push_back(v);
	for(int v:era)
		se.erase(v);
	for(int v:era)
		dfs(v);
}
int main(){
	int n,m,a,b,cnt=0;
	scanf("%d %d",&n,&m);
	for(int i=0;i<m;i++){
		scanf("%d %d",&a,&b);
		graph[a].insert(b);
		graph[b].insert(a);
	}
	for(int i=1;i<=n;i++)se.insert(i);
	for(int i=1;i<=n;i++){
		if(se.count(i)){
			dfs(i);
			cnt++;
		}
	}
	printf("%d\n",cnt-1);
}


#include<bits/stdc++.h>
using namespace std;
unordered_set<int> graph[100005];
unordered_set<int> se;
namespace IO{
	char ss[1<<17],*A=ss,*B=ss;
	inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	template<class T>inline void sd(T&x){
		char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45){y=-1;}x=c-48;
		while(c=gc(),47<c&&c<58){x=x*10+c-48;}x*=y;
	}
}
using namespace IO;
void bfs(int u) {
	queue<int> q;
	q.push(u);
	while(q.size()){
		u=q.front();
		q.pop();
		for(auto it=se.begin();it!=se.end();){
			int v=*it++;
			if(!graph[u].count(v))
				q.push(v),se.erase(v);
		}
	}
}
int main(){
	int n,m,a,b,cnt=0;
	sd(n),sd(m);
	for(int i=0;i<m;i++){
		sd(a),sd(b);
		graph[a].insert(b);
		graph[b].insert(a);
	}
	for(int i=1;i<=n;i++)se.insert(i);
	for(int i=1;i<=n;i++){
		if(se.count(i)){
			bfs(i);
			cnt++;
		}
	}
	printf("%d\n",cnt-1);
}


#include<bits/stdc++.h>
using namespace std;
unordered_set<long long int> graph;
unordered_set<int> se;
namespace IO{
	char ss[1<<17],*A=ss,*B=ss;
	inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	template<class T>inline void sd(T&x){
		char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45){y=-1;}x=c-48;
		while(c=gc(),47<c&&c<58){x=x*10+c-48;}x*=y;
	}
}
using namespace IO;
unordered_set<int>::iterator it;
int n,m,a,b,v,cnt=0;
queue<int> q;
unordered_set<int>::iterator bfs(int u) {
	q.push(u);
	while(q.size()){
		u=q.front();
		q.pop();
		for(it=se.begin();it!=se.end();){
			v=*it++;
			if(!graph.count(min(u,v)*1000000+max(u,v)))
				q.push(v),se.erase(v);
		}
	}
	return se.begin();
}
int main(){
	sd(n),sd(m);
	for(int i=0;i<m;i++){
		sd(a),sd(b);
		graph.insert(min(a,b)*1000000+max(a,b));
	}
	for(int i=1;i<=n;i++)se.insert(i);
	unordered_set<int>::iterator now=se.begin();
	while((now=bfs(*now))!=se.end()){
		cnt++;
	}
	printf("%d\n",cnt);
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
unordered_set<ll> mape;
vector<ll> graph[100005];
vector<pll> edge;
set<vector<ll> > ans;
int main(){
	ll n,m;
	cin>>n>>m;
	ll a,b;
	for(int i=0;i<m;i++){
		cin>>a>>b;
		edge.push_back({a,b});
		edge.push_back({b,a});
		mape.insert(a*1000000+b);
		mape.insert(b*1000000+a);
		graph[a].push_back(b);
		graph[b].push_back(a);
	}
	for(int i=0;i<m*2;i++){
		pll e = edge[i];
		vector<ll> vec;
		for(auto it:graph[e.first]){
			if(mape.count(it*1000000+e.second)){
				vec.push_back(it);
				cout<<e.first<<" "<<e.second<<" "<<it<<endl;
			}
		}
		if(vec.size()){
			sort(vec.begin(),vec.end());
			ans.insert(vec);
		}
	}
	if(ans.size())
		cout<<ans.size()-1<<endl;
	else if(n==2&&m==1)
		cout<<1<<endl;
	else
		cout<<0<<endl;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
unordered_set<ll> graph[100005];
unordered_set<ll> se;
void bfs(int u) {
	queue<ll> q;
	q.push(u);
	vector<ll> era;
	while(q.size()){
		u=q.front();
		q.pop();
		era.clear();
		for(ll v:se)
			if(!graph[u].count(v))
				era.push_back(v),q.push(v);
		for(ll v:era)
			se.erase(v);
	}
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie();
	ll n,m;
	cin>>n>>m;
	ll a,b;
	for(int i=0;i<m;i++){
		cin>>a>>b;
		graph[a].insert(b);
		graph[b].insert(a);
	}
	for(int i=1;i<=n;i++)se.insert(i);
	int cnt=0;
	for(int i=1;i<=n;i++){
		if(se.count(i)){
			bfs(i);
			cnt++;
		}
	}
	cout<<cnt-1<<endl;
}


#include<bits/stdc++.h>
using namespace std;
unordered_set<long long int> graph;
unordered_set<int> se;
namespace IO{
	char ss[1<<17],*A=ss,*B=ss;
	inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	template<class T>inline void sd(T&x){
		char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45){y=-1;}x=c-48;
		while(c=gc(),47<c&&c<58){x=x*10+c-48;}x*=y;
	}
}
using namespace IO;
unordered_set<int>::iterator it;
int n,m,a,b,v,i,cnt=0,ft=0,rr=0;
int q[100005];
unordered_set<int>::iterator bfs(int u) {
	q[rr++]=u;
	se.erase(u);
	while(rr-ft){
		u=q[ft++];
		for(it=se.begin();it!=se.end();){
			v=*it++;
			if(!graph.count(min(u,v)*1000000+max(u,v)))
				q[rr++]=v,se.erase(v);
		}
	}
	return se.begin();
}
int main(){
	sd(n),sd(m);
	for(i=0;i<m;i++){
		sd(a),sd(b);
		graph.insert(min(a,b)*1000000+max(a,b));
	}
	for(i=1;i<=n;i++)se.insert(i);
	unordered_set<int>::iterator now=se.begin();
	while((now=bfs(*now))!=se.end()){
		cnt++;
	}
	printf("%d\n",cnt);
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
unordered_set<ll> graph[100005];
unordered_set<ll> se;
void dfs(int u){
	for(ll v:se)
		if(!graph[u].count(v))
			dfs(v);
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie();
	ll n,m;
	cin>>n>>m;
	ll a,b;
	for(int i=0;i<m;i++){
		cin>>a>>b;
		graph[a].insert(b);
		graph[b].insert(a);
	}
	for(int i=1;i<=n;i++)se.insert(i);
	int cnt=0;
	for(int i=1;i<=n;i++){
		if(se.count(i)){
			dfs(i);
			cnt++;
		}
	}
	cout<<cnt-1<<endl;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
unordered_set<ll> graph[100005];
unordered_set<ll> se;
void dfs(int u){
	vector<ll> era;
	era.clear();
	for(ll v:se)
		if(!graph[u].count(v))
			era.push_back(v);
	for(ll v:era)
		se.erase(v);
	for(ll v:era)
		dfs(v);
}
int main(){
	ll n,m;
	cin>>n>>m;
	ll a,b;
	for(int i=0;i<m;i++){
		cin>>a>>b;
		graph[a].insert(b);
		graph[b].insert(a);
	}
	for(int i=1;i<=n;i++)se.insert(i);
	int cnt=0;
	for(int i=1;i<=n;i++){
		if(se.count(i)){
			dfs(i);
			cnt++;
		}
	}
	cout<<cnt-1<<endl;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
unordered_set<ll> mape;
vector<ll> graph[100005];
vector<pll> edge;
set<vector<ll> > ans;
int main(){
	ll n,m;
	cin>>n>>m;
	ll a,b;
	for(int i=0;i<m;i++){
		cin>>a>>b;
		edge.push_back({a,b});
		edge.push_back({b,a});
		mape.insert(a*1000000+b);
		mape.insert(b*1000000+a);
		graph[a].push_back(b);
		graph[b].push_back(a);
	}
	for(int i=0;i<m*2;i++){
		pll e = edge[i];
		vector<ll> vec;
		for(auto it:graph[e.first]){
			if(mape.count(it*1000000+e.second)){
				vec.push_back(it);
				//cout<<e.first<<" "<<e.second<<" "<<it<<endl;
			}
		}
		if(vec.size()){
			sort(vec.begin(),vec.end());
			ans.insert(vec);
		}
	}
	if(ans.size())
		cout<<ans.size()-1<<endl;
	else
		cout<<0<<endl;
}


#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
typedef long long int ll;
typedef cc_hash_table<ll, ll, hash<ll>> ht;
ht graph;
unordered_set<int> se;
namespace IO{
	char ss[1<<17],*A=ss,*B=ss;
	inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	template<class T>inline void sd(T&x){
		char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45){y=-1;}x=c-48;
		while(c=gc(),47<c&&c<58){x=x*10+c-48;}x*=y;
	}
}
using namespace IO;
unordered_set<int>::iterator it;
int n,m,a,b,v,i,cnt=0;
queue<int> q;
unordered_set<int>::iterator bfs(int u) {
	q.push(u);
	se.erase(u);
	while(q.size()){
		u=q.front();
		q.pop();
		for(it=se.begin();it!=se.end();){
			v=*it++;
			if(!graph[min(u,v)*1000000+max(u,v)]){
				q.push(v),se.erase(v);
			}
		}
	}
	return se.begin();
}
int main(){
	sd(n),sd(m);
	for(i=0;i<m;i++){
		sd(a),sd(b);
		graph[min(a,b)*1000000+max(a,b)]=1;
	}
	for(i=1;i<=n;i++)se.insert(i);
	unordered_set<int>::iterator now=se.begin();
	while((now=bfs(*now))!=se.end()){
		cnt++;
	}
	printf("%d\n",cnt);
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
unordered_set<ll> graph[100005];
set<ll> se;
void dfs(int u){
	se.erase(u);
	for(int v:se)
		if(!graph[u].count(v))
			dfs(v);
}
int main(){
	ll n,m;
	cin>>n>>m;
	ll a,b;
	for(int i=0;i<m;i++){
		cin>>a>>b;
		graph[a].insert(b);
		graph[b].insert(a);
	}
	for(int i=1;i<=n;i++)se.insert(i);
	int cnt=0;
	for(int i=1;i<=n;i++){
		if(se.count(i)){
			dfs(i);
			cnt++;
		}
	}
	cout<<cnt-1<<endl;
}


#include<bits/stdc++.h>
using namespace std;
unordered_set<long long int> graph;
unordered_set<int> se;
namespace IO{
	char ss[1<<17],*A=ss,*B=ss;
	inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	template<class T>inline void sd(T&x){
		char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45){y=-1;}x=c-48;
		while(c=gc(),47<c&&c<58){x=x*10+c-48;}x*=y;
	}
}
using namespace IO;
unordered_set<int>::iterator it,now;
int n,m,u,v,i,cnt=0,ft=0,rr=0;
int q[100005];
void bfs() {
	q[rr++]=*now;
	se.erase(*now);
	while(rr-ft){
		u=q[ft++];
		for(it=se.begin();it!=se.end();){
			v=*it++;
			if(!graph.count(min(u,v)*1000000+max(u,v))){
				q[rr++]=v,se.erase(v);
			}
		}
	}
	now=se.begin();
}
int main(){
	sd(n),sd(m);
	for(i=0;i<m;i++){
		sd(u),sd(v);
		graph.insert(min(u,v)*1000000+max(u,v));
	}
	for(i=1;i<=n;i++)se.insert(i);
	now=se.begin();
	while(now!=se.end()){
		bfs();
		cnt++;
	}
	printf("%d\n",cnt-1);
}


#include<bits/stdc++.h>
using namespace std;
unordered_set<int> graph[100005];
unordered_set<int> se;
namespace IO{
	char ss[1<<17],*A=ss,*B=ss;
	inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	template<class T>inline void sd(T&x){
		char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45){y=-1;}x=c-48;
		while(c=gc(),47<c&&c<58){x=x*10+c-48;}x*=y;
	}
}
using namespace IO;
unordered_set<int>::iterator bfs(int u) {
	queue<int> q;
	q.push(u);
	int v;
	while(q.size()){
		u=q.front();
		q.pop();
		for(unordered_set<int>::iterator it=se.begin();it!=se.end();){
			v=*it++;
			if(!graph[min(u,v)].count(max(u,v)))
				q.push(v),se.erase(v);
		}
	}
	return se.begin();
}
int main(){
	int n,m,a,b,cnt=0;
	sd(n),sd(m);
	for(int i=0;i<m;i++){
		sd(a),sd(b);
		graph[min(a,b)].insert(max(a,b));
	}
	for(int i=1;i<=n;i++)se.insert(i);
	unordered_set<int>::iterator now=se.begin();
	while((now=bfs(*now))!=se.end()){
		cnt++;
	}
	printf("%d\n",cnt);
}


#include<bits/stdc++.h>
using namespace std;
unordered_set<int> graph;
unordered_set<int> se;
namespace IO{
	char ss[1<<17],*A=ss,*B=ss;
	inline char gc(){return A==B&&(B=(A=ss)+fread_unlocked(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	template<class T>inline void sd(T&x){
		char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45){y=-1;}x=c-48;
		while(c=gc(),47<c&&c<58){x=x*10+c-48;}x*=y;
	}
}
using namespace IO;
unordered_set<int>::iterator it;
int n,m,a,b,v,i,cnt=0;
queue<int> q;
unordered_set<int>::iterator bfs(int u) {
	q.push(u);
	while(q.size()){
		u=q.front();
		q.pop();
		for(it=se.begin();it!=se.end();){
			v=*it++;
			if(!graph.count(min(u,v)*100000+max(u,v)))
				q.push(v),se.erase(v);
		}
	}
	return se.begin();
}
int main(){
	sd(n),sd(m);
	for(i=0;i<m;i++){
		sd(a),sd(b);
		graph.insert(min(a,b)*100000+max(a,b));
	}
	for(i=1;i<=n;i++)se.insert(i);
	unordered_set<int>::iterator now=se.begin();
	while((now=bfs(*now))!=se.end()){
		cnt++;
	}
	printf("%d\n",cnt);
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pll> vll;
typedef vector<pdd> vdd;
typedef vector<vl> vvl;
typedef vector<vd> vvd;
const int mod = 1000000007;
const vi mods = {998244353,1000000007,1000000009};
const ll inf = 3e18;
const double pi = acos(-1.0);
const double eps = 0.0000001;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define rep(i,a,b) for(ll i=(a);i<(b);++i)
#define trav(a,x) for(auto&a:x)
#define all(x) begin(x),end(x)
#define sz(x) ((int)(x).size())
#define fll(xs,x,a) fill(&x,&x+sizeof(xs)/sizeof(x),a)
#define has(x,a) (x.find(a)!=end(x))
#define pc(x) __builtin_popcountll(x)
#define pb push_back
#define fi first
#define se second
template<class...K> using umap = unordered_map<K...>;
template<class...K> using uset = unordered_set<K...>;

ll n,m,res;
umap<ll,vl>ig;
uset<ll>dh;

void ff(ll node){
  if(has(dh,node)){
    dh.erase(node);
    uset<ll>nxdh;
    trav(nx,ig[node]){
      if(has(dh,nx))nxdh.insert(nx);
    }
    dh=nxdh;
    trav(nx,ig[node]){
      ll cnt=0;
      trav(nx_,ig[nx]){
        if(has(dh,nx_))cnt++;
      }
      if(sz(dh)+sz(ig[nx])-cnt==n);
      else ff(nx);
    }
  }
}
int main() {
  cin.sync_with_stdio(0);
  cin.tie(0);
  cout.precision(13);
  cin>>n>>m;
  rep(i,0,m){
    ll u,v;cin>>u>>v;
    u--;v--;
    ig[u].pb(v);
    ig[v].pb(u);
  }
  // test tert cnn
  rep(i,0,n)dh.insert(i);
  ff(0);
  while(sz(dh)){
    ll node=*begin(dh);
    ll cnt=0;
    trav(nx,ig[node]){
      if(has(dh,nx))cnt++;
    }
    if(sz(dh)+sz(ig[node])-cnt==n)res++;
    ff(node);
  }
  cout<<res<<"\n";
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pll> vll;
typedef vector<pdd> vdd;
typedef vector<vl> vvl;
typedef vector<vd> vvd;
const int mod = 1000000007;
const vi mods = {998244353,1000000007,1000000009};
const ll inf = 3e18;
const double pi = acos(-1.0);
const double eps = 0.0000001;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define rep(i,a,b) for(ll i=(a);i<(b);++i)
#define trav(a,x) for(auto&a:x)
#define all(x) begin(x),end(x)
#define sz(x) ((int)(x).size())
#define fll(xs,x,a) fill(&x,&x+sizeof(xs)/sizeof(x),a)
#define has(x,a) (x.find(a)!=end(x))
#define pc(x) __builtin_popcountll(x)
#define pb push_back
#define fi first
#define se second
template<class...K> using umap = unordered_map<K...>;
template<class...K> using uset = unordered_set<K...>;

ll n,m,res;
umap<ll,vl>ig;
uset<ll>dh;

void ff(ll node){
  if(has(dh,node)){
    dh.erase(node);
    uset<ll>nxdh;
    trav(nx,ig[node]){
      if(has(dh,nx))nxdh.insert(nx);
    }
    dh=nxdh;
    trav(nx,ig[node]){
      ll cnt=0;
      trav(nx_,ig[nx]){
        if(has(dh,nx_))cnt++;
      }
      if(sz(dh)+sz(ig[nx])-cnt==n);
      else ff(nx);
    }
  }
}
int main() {
  cin.sync_with_stdio(0);
  cin.tie(0);
  cout.precision(13);
  cin>>n>>m;
  rep(i,0,m){
    ll u,v;cin>>u>>v;
    u--;v--;
    ig[u].pb(v);
    ig[v].pb(u);
  }
  // test tert cnn
  rep(i,0,n)dh.insert(i);
  ff(0);
  while(sz(dh)){
    ll node=*begin(dh);
    ff(node);
  }
  cout<<res<<"\n";
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pll> vll;
typedef vector<pdd> vdd;
typedef vector<vl> vvl;
typedef vector<vd> vvd;
const int mod = 1000000007;
const vi mods = {998244353,1000000007,1000000009};
const ll inf = 3e18;
const double pi = acos(-1.0);
const double eps = 0.0000001;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define rep(i,a,b) for(ll i=(a);i<(b);++i)
#define trav(a,x) for(auto&a:x)
#define all(x) begin(x),end(x)
#define sz(x) ((int)(x).size())
#define fll(xs,x,a) fill(&x,&x+sizeof(xs)/sizeof(x),a)
#define has(x,a) (x.find(a)!=end(x))
#define pc(x) __builtin_popcountll(x)
#define pb push_back
#define fi first
#define se second
template<class...K> using umap = unordered_map<K...>;
template<class...K> using uset = unordered_set<K...>;

ll n,m,res;
umap<ll,uset<ll>>ig;
set<ll>dh;

void ff(ll node){
  if(!has(dh,node))return;
  dh.erase(node);
  ll cur=-1;
  while(1){
    auto it=upper_bound(all(dh),cur);
    if(it==end(dh)) break;
    cur=*it;
    if(has(ig[node],cur))continue;
    ff(cur);
  }
}
int main() {
  cin.sync_with_stdio(0);
  cin.tie(0);
  cout.precision(13);
  cin>>n>>m;
  rep(i,0,m){
    ll u,v;cin>>u>>v;
    u--;v--;
    ig[u].insert(v);
    ig[v].insert(u);
  }
  rep(i,0,n)dh.insert(i);
  rep(i,0,n){
    if(!has(dh,i))continue;
    ff(i);
    res++;
  }
  res--;
  cout<<res<<"\n";
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pll> vll;
typedef vector<pdd> vdd;
typedef vector<vl> vvl;
typedef vector<vd> vvd;
const int mod = 1000000007;
const vi mods = {998244353,1000000007,1000000009};
const ll inf = 3e18;
const double pi = acos(-1.0);
const double eps = 0.0000001;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define rep(i,a,b) for(ll i=(a);i<(b);++i)
#define trav(a,x) for(auto&a:x)
#define all(x) begin(x),end(x)
#define sz(x) ((int)(x).size())
#define fll(xs,x,a) fill(&x,&x+sizeof(xs)/sizeof(x),a)
#define has(x,a) (x.find(a)!=end(x))
#define pc(x) __builtin_popcountll(x)
#define pb push_back
#define fi first
#define se second
template<class...K> using umap = unordered_map<K...>;
template<class...K> using uset = unordered_set<K...>;

ll n,m,res;
umap<ll,uset<ll>>ig;
set<ll>dh;

void ff(ll node){
  if(!has(dh,node))return;
  dh.erase(node);
  ll cur=-1;
  while(1){
    auto it=dh.upper_bound(cur);
    if(it==end(dh)) break;
    cur=*it;
    if(has(ig[node],cur))continue;
    ff(cur);
  }
}
int main() {
  cin.sync_with_stdio(0);
  cin.tie(0);
  cout.precision(13);
  cin>>n>>m;
  rep(i,0,m){
    ll u,v;cin>>u>>v;
    u--;v--;
    ig[u].insert(v);
    ig[v].insert(u);
  }
  rep(i,0,n)dh.insert(i);
  rep(i,0,n){
    if(!has(dh,i))continue;
    ff(i);
    res++;
  }
  res--;
  cout<<res<<"\n";
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pll> vll;
typedef vector<pdd> vdd;
typedef vector<vl> vvl;
typedef vector<vd> vvd;
const int mod = 1000000007;
const vi mods = {998244353,1000000007,1000000009};
const ll inf = 3e18;
const double pi = acos(-1.0);
const double eps = 0.0000001;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define rep(i,a,b) for(ll i=(a);i<(b);++i)
#define trav(a,x) for(auto&a:x)
#define all(x) begin(x),end(x)
#define sz(x) ((int)(x).size())
#define fll(xs,x,a) fill(&x,&x+sizeof(xs)/sizeof(x),a)
#define has(x,a) (x.find(a)!=end(x))
#define pc(x) __builtin_popcountll(x)
#define pb push_back
#define fi first
#define se second
template<class...K> using umap = unordered_map<K...>;
template<class...K> using uset = unordered_set<K...>;

ll n,m,res;
umap<ll,vl>ig;
uset<ll>dh;

void ff(ll node){
  if(has(dh,node)){
    dh.erase(node);
    trav(nx,ig[node]){
      ll cnt=0;
      trav(nx_,ig[nx]){
        if(has(dh,nx_))cnt++;
      }
      if(sz(dh)+sz(ig[nx])-cnt==n);
      else ff(nx);
    }
  }
}
int main() {
  cin.sync_with_stdio(0);
  cin.tie(0);
  cout.precision(13);
  cin>>n>>m;
  rep(i,0,m){
    ll u,v;cin>>u>>v;
    u--;v--;
    ig[u].pb(v);
    ig[v].pb(u);
  }
  // test tert cnn
  rep(i,0,n)dh.insert(i);
  ff(0);
  while(sz(dh)){
    ll node=*begin(dh);
    ll cnt=0;
    trav(nx,ig[node]){
      if(has(dh,nx))cnt++;
    }
    if(sz(dh)+sz(ig[node])-cnt==n)res++;
    ff(node);
  }
  cout<<res<<"\n";
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pll> vll;
typedef vector<pdd> vdd;
typedef vector<vl> vvl;
typedef vector<vd> vvd;
const int mod = 1000000007;
const vi mods = {998244353,1000000007,1000000009};
const ll inf = 3e18;
const double pi = acos(-1.0);
const double eps = 0.0000001;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define rep(i,a,b) for(ll i=(a);i<(b);++i)
#define trav(a,x) for(auto&a:x)
#define all(x) begin(x),end(x)
#define sz(x) ((int)(x).size())
#define fll(xs,x,a) fill(&x,&x+sizeof(xs)/sizeof(x),a)
#define has(x,a) (x.find(a)!=end(x))
#define pc(x) __builtin_popcountll(x)
#define pb push_back
#define fi first
#define se second
template<class...K> using umap = unordered_map<K...>;
template<class...K> using uset = unordered_set<K...>;

ll n,m,res;
umap<ll,uset<ll>>ig;
set<ll>dh;

void ff(ll node){
  if(!has(dh,node))return;
  dh.erase(node);
  ll cur=-1;
  while(1){
    auto it=upper_bound(all(dh),cur);
    if(it==end(dh)) break;
    cur=*it;
    if(has(ig[node],cur))continue;
    ff(cur);
  }
}
int main() {
  cin.sync_with_stdio(0);
  cin.tie(0);
  cout.precision(13);
  cin>>n>>m;
  rep(i,0,m){
    ll u,v;cin>>u>>v;
    u--;v--;
    ig[u].insert(v);
    ig[v].insert(u);
  }
  rep(i,0,n)dh.insert(i);
  ff(0);
  while(sz(dh)){
    ff(*begin(dh));
    res++;
  }
  cout<<res<<"\n";
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pll> vll;
typedef vector<pdd> vdd;
typedef vector<vl> vvl;
typedef vector<vd> vvd;
const int mod = 1000000007;
const vi mods = {998244353,1000000007,1000000009};
const ll inf = 3e18;
const double pi = acos(-1.0);
const double eps = 0.0000001;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define rep(i,a,b) for(ll i=(a);i<(b);++i)
#define trav(a,x) for(auto&a:x)
#define all(x) begin(x),end(x)
#define sz(x) ((int)(x).size())
#define fll(xs,x,a) fill(&x,&x+sizeof(xs)/sizeof(x),a)
#define has(x,a) (x.find(a)!=end(x))
#define pc(x) __builtin_popcountll(x)
#define pb push_back
#define fi first
#define se second
template<class...K> using umap = unordered_map<K...>;
template<class...K> using uset = unordered_set<K...>;

#define N 100100
ll n,m,res;
umap<ll,vl>ig;
uset<ll>dh;

int main() {
  cin.sync_with_stdio(0);
  cin.tie(0);
  cout.precision(13);
  cin>>n>>m;
  rep(i,0,m){
    ll u,v;cin>>u>>v;
    u--;v--;
    ig[u].pb(v);
    ig[v].pb(u);
  }
  trav(z_,ig[0])dh.insert(z_);
  while(sz(dh)){
    ll node=*begin(dh);
    uset<ll>nxdh;
    trav(nx,ig[node]){
      if(has(dh,nx))nxdh.insert(nx);
    }
    dh=nxdh;
    res++;
  }
  cout<<res<<"\n";
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pll> vll;
typedef vector<pdd> vdd;
typedef vector<vl> vvl;
typedef vector<vd> vvd;
const int mod = 1000000007;
const vi mods = {998244353,1000000007,1000000009};
const ll inf = 3e18;
const double pi = acos(-1.0);
const double eps = 0.0000001;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define rep(i,a,b) for(ll i=(a);i<(b);++i)
#define trav(a,x) for(auto&a:x)
#define all(x) begin(x),end(x)
#define sz(x) ((int)(x).size())
#define fll(xs,x,a) fill(&x,&x+sizeof(xs)/sizeof(x),a)
#define has(x,a) (x.find(a)!=end(x))
#define pc(x) __builtin_popcountll(x)
#define pb push_back
#define fi first
#define se second
template<class...K> using umap = unordered_map<K...>;
template<class...K> using uset = unordered_set<K...>;

ll n,m,res;
umap<ll,vl>ig;
uset<ll>dh;

void ff(ll node){
  if(has(dh,node)){
    dh.erase(node);
    uset<ll>nxdh;
    trav(nx,ig[node]){
      if(has(dh,nx))nxdh.insert(nx);
    }
    dh=nxdh;
    trav(nx,ig[node]){
      ll cnt=0;
      trav(nx_,ig[nx]){
        if(has(dh,nx_))cnt++;
      }
      if(sz(dh)+sz(ig[nx])-cnt==n);
      else ff(nx);
    }
  }
}
int main() {
  cin.sync_with_stdio(0);
  cin.tie(0);
  cout.precision(13);
  cin>>n>>m;
  rep(i,0,m){
    ll u,v;cin>>u>>v;
    u--;v--;
    ig[u].pb(v);
    ig[v].pb(u);
  }
  // test tert cnn
  rep(i,0,n)dh.insert(i);
  ff(0);
  while(sz(dh)){
    ff(*begin(dh));
    res++;
  }
  cout<<res<<"\n";
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
vector<set<ll>>v(100002);
set <ll> s;
void dfs(ll x)
{
    s.erase(x);
    for(auto i:s)
    {
        if(v[x].find(i)==v[x].end() )
        {
            s.erase(x);
            dfs(i);

        }
    }
}
int main()
{
    ll n,m;
    cin>>n>>m;
    ll x,y;
    while(m--)
    {
        cin>>x>>y;
        v[x].insert(y);
        v[y].insert(x);
    }
    for(ll i=1;i<=n;i++)
    {
        s.insert(i);
    }
    ll count=0;
    for(ll i=1;i<=n;i++)
    {
        if(s.find(i)!=s.end())
        {
            s.erase(i);
            dfs(i);
            count++;
        }
    }
    cout<<count-1;
    s.clear();

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
vector<set<ll>> v(100002);
set<ll> s;
void dfs(ll x)
{
    s.erase(x);
    for (auto i : s)
    {
        if (v[x].find(i) == v[x].end())
        {
            s.erase(x);
            dfs(i);
        }
    }
}
int main()
{
    ll n, m;
    cin >> n >> m;
    ll x, y;
    while (m--)
    {
        cin >> x >> y;
        v[x].insert(y);
        v[y].insert(x);
    }
    for (ll i = 1; i <= n; i++)
    {
        s.insert(i);
    }
    ll count = 0;
    for (ll i = 1; i <= n; i++)
    {
        if (s.find(i) != s.end())
        {
            s.erase(i);
            dfs(i);
            count++;
        }
    }
    cout << count - 1;
    s.clear();

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
vector<set<ll>> v(100002);
set<ll> s;
void dfs(ll x)
{
    s.erase(x);
    for (auto i : s)
    {
        if (v[x].find(i) == v[x].end())
        {
            s.erase(x);
            dfs(i);
        }
    }
}
int main()
{
    ll n, m;
    cin >> n >> m;
    ll x, y;
    while (m--)
    {
        cin >> x >> y;
        v[x].insert(y);
        v[y].insert(x);
    }
    for (ll i = 1; i <= n; i++)
    {
        s.insert(i);
    }
    ll count = 0;
    for (auto i:s)
    {
        if (s.find(i) != s.end())
        {
            s.erase(i);
            dfs(i);
            count++;
        }
    }
    cout << count - 1;
    s.clear();

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
vector<set<ll>>v(100002);
set <ll> s;
void dfs(ll x)
{

    s.erase(x);
    for(auto i=s.begin();i!=s.end();i++)
    {
        if(v[x].find(*i)==v[x].end() )
        {
            s.erase(*i);
            dfs(*i);

        }
    }
}
int main()
{
    ll n,m;
    cin>>n>>m;
    ll x,y;
    while(m--)
    {
        cin>>x>>y;
        v[x].insert(y);
        v[y].insert(x);
    }
    for(ll i=1;i<=n;i++)
    {
        v[i].insert(0);
        s.insert(i);
    }
    ll count=0;
    for(ll i=1;i<=n;i++)
    {
        if(s.find(i)!=s.end())
        {
            s.erase(i);
            dfs(i);
            count++;
        }
    }
    cout<<count-1;
    s.clear();

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
vector<set<ll>> v(100002);
set<ll> s;
void dfs(ll x)
{
    s.erase(x);
    auto i=s.begin();
    while(i!=s.end())
    {
        if (v[x].find(*i) == v[x].end())
        {
            s.erase(*i);
            dfs(*i);
            i++;
        }
        else
        {
            i++;
        }

    }
}
int main()
{
    ll n, m;
    cin >> n >> m;
    ll x, y;
    while (m--)
    {
        cin >> x >> y;
        v[x].insert(y);
        v[y].insert(x);
    }
    for (ll i = 1; i <= n; i++)
    {
        s.insert(i);
    }
    ll count = 0;
    for (ll i=1;i<=n;i++)
    {
        if (s.find(i) != s.end())
        {
            s.erase(i);
            dfs(i);
            count++;
        }
    }
    cout << count - 1;
    s.clear();

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
vector<set<ll>> v(100002);
set<ll> s;
void dfs(ll x)
{
    s.erase(x);

    stack<ll> st;
    st.push(x);
    while (!st.empty())
    {
        auto i = s.begin();
        ll y = st.top();
        st.pop();
        while (i != s.end())
        {
            if (v[y].find(*i) == v[y].end())
            {
                s.erase(i);
                st.push(*i);
                i++;
            }
            else
            {
                i++;
            }
        }
    }
}
int main()
{
    ll n, m;
    cin >> n >> m;
    ll x, y;
    while (m--)
    {
        cin >> x >> y;
        v[x].insert(y);
        v[y].insert(x);
    }
    for (ll i = 1; i <= n; i++)
    {
        s.insert(i);
    }
    ll count = 0;
    for (ll i = 1; i <= n; i++)
    {
        if (s.find(i) != s.end())
        {
            s.erase(s.find(i));
            dfs(i);
            count++;
        }
    }
    cout << count - 1;
    s.clear();

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
vector<set<ll>> v(100002);
set<ll> s;
void dfs(ll x)
{
    s.erase(x);
    auto i=s.begin();
    while(i!=s.end())
    {
        if (v[x].find(*i) == v[x].end())
        {
            s.erase(i);
            dfs(*i);
            i=s.lower_bound(*i);
        }
        else
        {
            i++;
        }

    }
}
int main()
{
    ll n, m;
    cin >> n >> m;
    ll x, y;
    while (m--)
    {
        cin >> x >> y;
        v[x].insert(y);
        v[y].insert(x);
    }
    for (ll i = 1; i <= n; i++)
    {
        s.insert(i);
    }
    ll count = 0;
    for (ll i=1;i<=n;i++)
    {
        if (s.find(i) != s.end())
        {
            s.erase(s.find(i));
            dfs(i);
            count++;
        }
    }
    cout << count - 1;
    s.clear();

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
vector<set<ll>> v(100002);
set<ll> s;
void dfs(ll x)
{
    s.erase(x);

    stack<ll> st;
    st.push(x);
    while (!st.empty())
    {
        // auto i = s.begin();
        ll y = st.top();
        st.pop();
        for(auto i:s)
        {
            if (v[y].find(i) == v[y].end())
            {
                s.erase(i);
                st.push(i);
                // i++;
            }
            // else
            // {
            //     i++;
            // }
        }
    }
}
int main()
{
    ll n, m;
    cin >> n >> m;
    ll x, y;
    while (m--)
    {
        cin >> x >> y;
        v[x].insert(y);
        v[y].insert(x);
    }
    for (ll i = 1; i <= n; i++)
    {
        s.insert(i);
    }
    ll count = 0;
    for (ll i = 1; i <= n; i++)
    {
        if (s.find(i) != s.end())
        {
            s.erase(s.find(i));
            dfs(i);
            count++;
        }
    }
    cout << count - 1;
    s.clear();

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
ll power(ll a, ll b)
{
    ll ans = 1;
    while (b)
    {
        if (b & 1)
            ans *= a;
        a *= a;
        b /= 2;
    }
    return ans;
}
ll n;
map<ll,int>mp[100002];
set <ll> s;
void dfs(ll x)
{
    s.erase(x);
    for(auto i:s)
    {
        if(mp[x].find(i)==mp[x].end() )
        {
            s.erase(x);
            dfs(i);

        }
    }
}
int main()
{
    ll m;
    cin>>n>>m;
    ll x,y;
    while(m--)
    {
        cin>>x>>y;
        mp[x][y]=1;
        mp[y][x]=1;
    }
    for(ll i=1;i<=n;i++)
    {
        s.insert(i);
    }
    ll count=0;
    for(ll i=1;i<=n;i++)
    {
        if(s.find(i)!=s.end())
        {
            s.erase(i);
            dfs(i);
            count++;
        }
    }
    cout<<count-1;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
vector<set<ll>>v(100002);
set <ll> s;
void dfs(ll x)
{

    s.erase(x);
    for(auto i=s.begin();i!=s.end();i++)
    {
        if(v[x].count(*i)==0 )
        {
            s.erase(*i);
            dfs(*i);

        }
    }
}
int main()
{
    ll n,m;
    cin>>n>>m;
    ll x,y;
    while(m--)
    {
        cin>>x>>y;
        v[x].insert(y);
        v[y].insert(x);
    }
    for(ll i=1;i<=n;i++)
    {
        v[i].insert(0);
        s.insert(i);
    }
    ll count=0;
    for(ll i=1;i<=n;i++)
    {
        if(s.find(i)!=s.end())
        {
            s.erase(i);
            dfs(i);
            count++;
        }
    }
    cout<<count-1;
    s.clear();

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
vector<set<ll>>v(100002);
set <ll> s;
void dfs(ll x)
{
    if(s.size()<=1)
    return ;
    s.erase(x);
    for(auto i:s)
    {
        if(v[x].count(i)==0 )
        {
            s.erase(i);
            dfs(i);

        }
    }
}
int main()
{
    ll n,m;
    cin>>n>>m;
    ll x,y;
    while(m--)
    {
        cin>>x>>y;
        v[x].insert(y);
        v[y].insert(x);
    }
    for(ll i=1;i<=n;i++)
    {
        v[i].insert(0);
        s.insert(i);
    }
    ll count=0;
    for(ll i=1;i<=n;i++)
    {
        if(s.find(i)!=s.end())
        {
            s.erase(i);
            dfs(i);
            count++;
        }
    }
    cout<<count-1;
    s.clear();

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
vector<set<ll>> v(100002);
set<ll> s;
void dfs(ll x)
{
    s.erase(x);
    auto i=s.begin();
    while(i!=s.end())
    {
        if (v[x].find(*i) == v[x].end())
        {
            s.erase(*i);
            dfs(*i);
            i=s.lower_bound(*i);
        }
        else
        {
            i++;
        }

    }
}
int main()
{
    ll n, m;
    cin >> n >> m;
    ll x, y;
    while (m--)
    {
        cin >> x >> y;
        v[x].insert(y);
        v[y].insert(x);
    }
    for (ll i = 1; i <= n; i++)
    {
        s.insert(i);
    }
    ll count = 0;
    for (ll i=1;i<=n;i++)
    {
        if (s.find(i) != s.end())
        {
            s.erase(i);
            dfs(i);
            count++;
        }
    }
    cout << count - 1;
    s.clear();

    return 0;
}


#include <bits/stdc++.h>

#define in insert
#define all(x) x.begin(), x.end()
#define sz(x) (int) x.size()
#define sqr(x) ((x) * (x))
#define pb push_back
#define fi first
#define se second
#define fr(i, l, r) for (int i = l; i <= r; ++i)
#define rf(i, r, l) for (int i = r; i >= l; --i)
#define fast_io ios_base::sync_with_stdio(0); cin.tie(0);
#define stop system("pause");
#define x1 fdffgahj
#define y1 fdffgga

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N = 2e5 + 10;
const int MXN = 30;
const int M = 5e3 + 10;
const int inf = 1e9;
const ll INF = 1e18 + 1e2;
const int mod = 1e9 + 7;

template <typename T>
void vout(T x){
    cout << x << endl;
    exit(0);
}

int n, m;
vector<int> v[N];

int main()
{
    fast_io

    cin >> n >> m;
    fr(i, 1, m) {
        int x, y;
        cin >> x >> y;
        if (x > y) swap(x, y);
        v[y].pb(x);
    }

    fr(i, 1, n) sort(all(v[i]));

    int ans = 0;
    fr(i, 2, n) {
        int cnt = 1;
        for (int j : v[i]) {
            if (j == cnt) cnt++;
            else break;
        }
        if (cnt > i - 1) ans++;
    }

    vout(ans);
    return 0;
}


#include <bits/stdc++.h>

#define in insert
#define all(x) x.begin(), x.end()
#define sz(x) (int) x.size()
#define sqr(x) ((x) * (x))
#define pb push_back
#define fi first
#define se second
#define fr(i, l, r) for (int i = l; i <= r; ++i)
#define rf(i, r, l) for (int i = r; i >= l; --i)
#define fast_io ios_base::sync_with_stdio(0); cin.tie(0);
#define stop system("pause");
#define x1 fdffgahj
#define y1 fdffgga

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N = 2e5 + 10;
const int MXN = 30;
const int M = 5e3 + 10;
const int inf = 1e9;
const ll INF = 1e18 + 1e2;
const int mod = 1e9 + 7;

template <typename T>
void vout(T x){
    cout << x << endl;
    exit(0);
}

int n, m;
vector<int> v[N];

int main()
{
    fast_io

    cin >> n >> m;
    fr(i, 1, m) {
        int x, y;
        cin >> x >> y;
        if (x > y) swap(x, y);
        v[y].pb(x);
        v[x].pb(y);
    }

    fr(i, 1, n) sort(all(v[i]));

    int ans = 0;
    fr(i, 2, n) {
        int cnt = 1;
        for (int j : v[i]) {
            if (j == cnt) cnt++;
            else break;
        }
        if (cnt > i - 1) ans++;
    }

    vout(ans);
    return 0;
}


#include <bits/stdc++.h>

#define in insert
#define all(x) x.begin(), x.end()
#define sz(x) (int) x.size()
#define sqr(x) ((x) * (x))
#define pb push_back
#define fi first
#define se second
#define fr(i, l, r) for (int i = l; i <= r; ++i)
#define rf(i, r, l) for (int i = r; i >= l; --i)
#define fast_io ios_base::sync_with_stdio(0); cin.tie(0);
#define stop system("pause");
#define x1 fdffgahj
#define y1 fdffgga

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N = 2e5 + 10;
const int MXN = 30;
const int M = 5e3 + 10;
const int inf = 1e9;
const ll INF = 1e18 + 1e2;
const int mod = 1e9 + 7;

template <typename T>
void vout(T x){
    cout << x << endl;
    exit(0);
}

int n, m;
vector<int> v[N];

int main()
{
    fast_io

    cin >> n >> m;
    fr(i, 1, m) {
        int x, y;
        cin >> x >> y;
        if (x > y) swap(x, y);
        v[y].pb(x);
    }

    fr(i, 1, n) sort(all(v[i]));

    int ans = 0;
    fr(i, 2, n) {
        int cnt = 1;
        for (int j : v[i]) if (j == cnt) cnt++;
        if (cnt > i - 1) ans++;
    }

    vout(ans);
    return 0;
}


#include <bits/stdc++.h>

#define in insert
#define all(x) x.begin(), x.end()
#define sz(x) (int) x.size()
#define sqr(x) ((x) * (x))
#define pb push_back
#define fi first
#define se second
#define fr(i, l, r) for (int i = l; i <= r; ++i)
#define rf(i, r, l) for (int i = r; i >= l; --i)
#define fast_io ios_base::sync_with_stdio(0); cin.tie(0);
#define stop system("pause");
#define x1 fdffgahj
#define y1 fdffgga

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N = 2e5 + 10;
const int MXN = 30;
const int M = 5e3 + 10;
const int inf = 1e9;
const ll INF = 1e18 + 1e2;
const int mod = 1e9 + 7;

template <typename T>
void vout(T x){
    cout << x << endl;
    exit(0);
}

int n, m;
vector<int> v[N];

int main()
{
    fast_io

    cin >> n >> m;
    fr(i, 1, m) {
        int x, y;
        cin >> x >> y;
        if (x > y) swap(x, y);
        v[y].pb(x);
    }

    fr(i, 1, n) sort(all(v[i]));

    int ans = 0;
    fr(i, 2, n)
        if (sz(v[i]) == i - 1) ans++;

    vout(ans);
    return 0;
}


#include <bits/stdc++.h>

#define in insert
#define all(x) x.begin(), x.end()
#define sz(x) (int) x.size()
#define sqr(x) ((x) * (x))
#define pb push_back
#define fi first
#define se second
#define fr(i, l, r) for (int i = l; i <= r; ++i)
#define rf(i, r, l) for (int i = r; i >= l; --i)
#define fast_io ios_base::sync_with_stdio(0); cin.tie(0);
#define stop system("pause");
#define x1 fdffgahj
#define y1 fdffgga

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N = 2e5 + 10;
const int MXN = 30;
const int M = 5e3 + 10;
const int inf = 1e9;
const ll INF = 1e18 + 1e2;
const int mod = 1e9 + 7;

template <typename T>
void vout(T x){
    cout << x << endl;
    exit(0);
}

int n, m, u[N];
vector<int> g[N];

void dfs(int x) {
    u[x] = 1;

    fr(i, 1, n) {
        if (u[i]) continue;
        int it = lower_bound(all(g[x]), i) - g[x].begin();
        if (g[x][it] == i) continue;
        dfs(i);
    }
}

int main()
{
    fast_io

    cin >> n >> m;
    fr(i, 1, m) {
        int x, y;
        cin >> x >> y;
        g[x].pb(y);
        g[y].pb(x);
    }

    fr(i, 1, n) {
        g[i].pb(n + 1);
        sort(all(g[i]));
    }

    int ans = 0;

    dfs(1);

    fr(i, 1, n) {
        if (!u[i]) {
            ans++;
            dfs(i);
        }
    }

    vout(ans);
    return 0;
}


#include <bits/stdc++.h>

#define in insert
#define all(x) x.begin(), x.end()
#define sz(x) (int) x.size()
#define sqr(x) ((x) * (x))
#define pb push_back
#define fi first
#define se second
#define fr(i, l, r) for (int i = l; i <= r; ++i)
#define rf(i, r, l) for (int i = r; i >= l; --i)
#define fast_io ios_base::sync_with_stdio(0); cin.tie(0);
#define stop system("pause");
#define x1 fdffgahj
#define y1 fdffgga

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N = 2e5 + 10;
const int MXN = 30;
const int M = 5e3 + 10;
const int inf = 1e9;
const ll INF = 1e18 + 1e2;
const int mod = 1e9 + 7;

template <typename T>
void vout(T x){
    cout << x << endl;
    exit(0);
}

int n, m, a[N], b[N];
vector<int> v[N], g[2];

bool cmp(int a, int b) {
    return sz(v[a]) < sz(v[b]);
}

int main()
{
    fast_io

    cin >> n >> m;
    fr(i, 1, m) {
        int x, y;
        cin >> x >> y;
        v[x].pb(y);
        v[y].pb(x);
    }

    fr(i, 1, n) a[i] = i;
    sort(a + 1, a + n + 1, cmp);

    fr(i, 1, n) b[a[i]] = i;

//    fr(i, 1, n) cerr << a[i] << " ";
//    cerr << endl;

    g[0].pb(1);

    int ans = 0;
    fr(i, 2, n) {
        for (auto j : v[a[i]]) g[1].pb(b[j]);
        sort(all(g[1]));

        g[1].pb(n + 1);
//        cerr << "step: " << i << " num = " << a[i] << endl;
//        for (auto j : g[0]) cerr << a[j] << " ";
//        cerr << endl;
//
//        for (auto j : g[1]) cerr << a[j] << " ";
//        cerr << endl;

        int last = -1;
        for (int j = 0; j <= min(sz(g[0]), sz(g[1])) - 1; ++j) {
            if (g[0][j] != g[1][j]) {
                last = j;
                break;
            }
        }

//        cerr << "||||||||||| " << last << endl;
        g[1].clear();
        g[0].pb(i);

        if (last == -1) ans++;
    }
    vout(ans);
    return 0;
}


#include <bits/stdc++.h>

#define in insert
#define all(x) x.begin(), x.end()
#define sz(x) (int) x.size()
#define sqr(x) ((x) * (x))
#define pb push_back
#define fi first
#define se second
#define fr(i, l, r) for (int i = l; i <= r; ++i)
#define rf(i, r, l) for (int i = r; i >= l; --i)
#define fast_io ios_base::sync_with_stdio(0); cin.tie(0);
#define stop system("pause");
#define x1 fdffgahj
#define y1 fdffgga

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N = 2e5 + 10;
const int MXN = 30;
const int M = 5e3 + 10;
const int inf = 1e9;
const ll INF = 1e18 + 1e2;
const int mod = 1e9 + 7;

template <typename T>
void vout(T x){
    cout << x << endl;
    exit(0);
}

int n, m, a[N], b[N];
vector<int> v[N], g[2];

bool cmp(int a, int b) {
    return sz(v[a]) < sz(v[b]);
}

int main()
{
    fast_io

    cin >> n >> m;
    fr(i, 1, m) {
        int x, y;
        cin >> x >> y;
        v[x].pb(y);
        v[y].pb(x);
    }

    fr(i, 1, n) a[i] = i;
    sort(a + 1, a + n + 1, cmp);

    fr(i, 1, n) b[a[i]] = i;

    fr(i, 1, n) cerr << a[i] << " ";
    cerr << endl;

    g[0].pb(1);

    int ans = 0;
    fr(i, 2, n) {
        for (auto j : v[a[i]]) g[1].pb(b[j]);
        sort(all(g[1]));

        g[1].pb(n + 1);
        cerr << "step: " << i << " num = " << a[i] << endl;
        for (auto j : g[0]) cerr << a[j] << " ";
        cerr << endl;

        for (auto j : g[1]) cerr << a[j] << " ";
        cerr << endl;

        int last = -1;
        for (int j = 0; j <= min(sz(g[0]), sz(g[1])) - 1; ++j) {
            if (g[0][j] != g[1][j]) {
                last = j;
                break;
            }
        }

        cerr << "||||||||||| " << last << endl;
        g[1].clear();
        g[0].pb(i);

        if (last == -1) ans++;
    }
    vout(ans);
    return 0;
}


#include <bits/stdc++.h>

#define in insert
#define all(x) x.begin(), x.end()
#define sz(x) (int) x.size()
#define sqr(x) ((x) * (x))
#define pb push_back
#define fi first
#define se second
#define fr(i, l, r) for (int i = l; i <= r; ++i)
#define rf(i, r, l) for (int i = r; i >= l; --i)
#define fast_io ios_base::sync_with_stdio(0); cin.tie(0);
#define stop system("pause");
#define x1 fdffgahj
#define y1 fdffgga

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N = 2e5 + 10;
const int MXN = 30;
const int M = 5e3 + 10;
const int inf = 1e9;
const ll INF = 1e18 + 1e2;
const int mod = 1e9 + 7;

template <typename T>
void vout(T x){
    cout << x << endl;
    exit(0);
}

int n, m, u[N];
vector<int> g[N];
set<int> st;

void dfs(int x) {
    u[x] = 1;
    st.erase(x);

    set<int> :: iterator it = st.begin();
    while(it != st.end()) {
        int now = *it;
        int pos = lower_bound(all(g[x]), now) - g[x].begin();
        if (g[x][pos] != now) dfs(now);
        it = st.upper_bound(now);
        if (now == *it) break;
    }
}

int main()
{
    fast_io

    cin >> n >> m;
    fr(i, 1, m) {
        int x, y;
        cin >> x >> y;
        g[x].pb(y);
        g[y].pb(x);
    }

    fr(i, 1, n) {
        st.in(i);
        g[i].pb(n + 1);
        sort(all(g[i]));
    }

    int ans = 0;

    dfs(1);

    fr(i, 1, n) {
        if (!u[i]) {
            ans++;
            dfs(i);
        }
    }

    vout(ans);
    return 0;
}


#include <bits/stdc++.h>

#define in insert
#define all(x) x.begin(), x.end()
#define sz(x) (int) x.size()
#define sqr(x) ((x) * (x))
#define pb push_back
#define fi first
#define se second
#define fr(i, l, r) for (int i = l; i <= r; ++i)
#define rf(i, r, l) for (int i = r; i >= l; --i)
#define fast_io ios_base::sync_with_stdio(0); cin.tie(0);
#define stop system("pause");
#define dbg(x) cerr << x;
#define x1 fdffgahj
#define y1 fdffgga

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N = 2e5 + 10;
const int MXN = 30;
const int M = 5e3 + 10;
const int inf = 1e9;
const ll INF = 1e18 + 1e2;
const int mod = 1e9 + 7;

template <typename T>
void vout(T x){
    cout << x << endl;
    exit(0);
}

int n, m, a[N], b[N];
vector<int> v[N];

struct low {
    int data;
    low *l, *r;

    low() {
        data = 0;
        l = r = nullptr;
    }

    ~low() {
        delete l;
        delete r;
    }
};

low* getl(low *v) {
    if (!v -> l) v -> l = new low();
    return v -> l;
}

low* getr(low *v) {
    if (!v -> r) v -> r = new low();
    return v -> r;
}

int get(low *v) {
    if (!v) return 0;
    return v -> data;
}

void calc(low *v) {
    v -> data = get(getl(v)) + get(getr(v));
}

void update(low *v, int l, int r, int pos) {
    if (l == r) v -> data = 1;
    else {
        int tm = (l + r) >> 1;
        if (pos <= tm) update(getl(v), l, tm, pos);
        else update(getr(v), tm + 1, r, pos);

        calc(v);
    }
}

int get(low *v1, low *v2, int l, int r) {
    if (l == r) return l;
    else {
        int tm = (l + r) / 2;
        if (get(getl(v1)) != get(getl(v2)))
            return get(getl(v1), getl(v2), l, tm);
        else return get(getr(v1), getr(v2), tm + 1, r);
    }
}

bool cmp(int a, int b) {
    return sz(v[a]) < sz(v[b]);
}

int main()
{
    fast_io

    cin >> n >> m;
    fr(i, 1, m) {
        int x, y;
        cin >> x >> y;
        v[x].pb(y);
        v[y].pb(x);
    }

    fr(i, 1, n) a[i] = i;
    sort(a + 1, a + n + 1, cmp);

    fr(i, 1, n) b[a[i]] = i;

    dbg("\n");

    low *root = new low();
    low *add;

    update(root, 1, n + 1, a[1]);
    update(root, 1, n + 1, n + 1);

    fr(i, 1, n) {
        dbg(a[i]); dbg(" ");
    }
    dbg("\n");

    int ans = 0;
    fr(i, 2, n) {
        add = new low();
        for (auto j : v[a[i]])
            update(add, 1, n + 1, j);

        int res = get(root, add, 1, n + 1);
        delete add;

        if (res == n + 1) ans++;
        dbg(a[res]); dbg(" ");
        update(root, 1, n + 1, a[i]);
    }
    dbg("\n");
    vout(ans);
    return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
#define first x
#define second y
#define sd(x) scanf("%d",&x)
#define slld(x) scanf("%lld",&x)
#define ss(x) scanf("%s",x)
#define FOR(k,a,b) for(int k=(a); k<=(b); ++k)
#define REP(k,a) for(int k=0; k<(a);++k)
#define SZ(a) int((a).size())
#define ALL(c) (c).begin(),(c).end()
#define PB push_back
#define MP make_pair
#define INF 999999999
#define INFLONG 1000000000000000000
#define MOD 1000000007
#define MAX 100
#define ITERS 100
#define MAXM 200000
#define MAXN 1000000
#define _gcd __gcd
#define eps 1e-9

int n, v;
vector<set<int> > nule(100100);
set<int> sol;
bool bio[100100]; int disi[100100];
void dfs(int x){

	if(bio[x]) return;
	bio[x] = true;
	REP(i, n){
		if(i != x && !bio[i]) {
			if(!nule[x].count(i)) dfs(i);
		}
	}
	return;
}

int main(){

	cin >> n >> v;
	 ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	REP(i, v){
		int a, b;
		cin >> a >> b;
		nule[a-1].insert(b-1);
		nule[b-1].insert(a-1);
	}
 	REP(i, n){
 		if(!bio[i]){
 			sol.insert(i);
			dfs(i);
		 }

	}
	cout << sol.size()-1 << endl;

}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
#define first x
#define second y
#define sd(x) scanf("%d",&x)
#define slld(x) scanf("%lld",&x)
#define ss(x) scanf("%s",x)
#define FOR(k,a,b) for(int k=(a); k<=(b); ++k)
#define REP(k,a) for(int k=0; k<(a);++k)
#define SZ(a) int((a).size())
#define ALL(c) (c).begin(),(c).end()
#define PB push_back
#define MP make_pair
#define INF 999999999
#define INFLONG 1000000000000000000
#define MOD 1000000007
#define MAX 100
#define ITERS 100
#define MAXM 200000
#define MAXN 1000000
#define _gcd __gcd
#define eps 1e-9

int n, v;
vector<set<pair<int, int> > > nule(100100);
set<int> sol;
bool bio[100100]; int disi[100100];
void dfs(int x, int idx){

	if(bio[x]) return;
	bio[x] = true;
	REP(i, n){
		if(i != x && !bio[i]) if(!nule[x].count(i)) dfs(i, idx);
	}
	return;
}

int main(){

	cin >> n >> v;
	  ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	REP(i, v){
		int a, b;
		cin >> a >> b;
		nule[a-1].insert({1, 1});
		nule[b-1].insert({1, 1});
	}
 	REP(i, n){
 		if(!bio[i]){
 			dfs(i, i);
		 }
	}
	cout << sol.size()-1 << endl;

}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
#define first x
#define second y
#define sd(x) scanf("%d",&x)
#define slld(x) scanf("%lld",&x)
#define ss(x) scanf("%s",x)
#define FOR(k,a,b) for(int k=(a); k<=(b); ++k)
#define REP(k,a) for(int k=0; k<(a);++k)
#define SZ(a) int((a).size())
#define ALL(c) (c).begin(),(c).end()
#define PB push_back
#define MP make_pair
#define INF 999999999
#define INFLONG 1000000000000000000
#define MOD 1000000007
#define MAX 100
#define ITERS 100
#define MAXM 200000
#define MAXN 1000000
#define _gcd __gcd
#define eps 1e-9

int n, v;
map<int, bool> mapa[100500];
int sol;
set<int> bio;
void dfs(int x){
	bio.erase(x);
	int temp = 0;
	while(!bio.empty()){
		set<int>::iterator it = bio.upper_bound(temp);

		if(it == bio.end()) break;
		temp = *it;
		if(!mapa[x].count(temp)) dfs(temp);

	}
	return;
}

int main(){

	cin >> n >> v;

	REP(i, v){
		int a, b;
		cin >> a >> b;
		mapa[a-1][b-1] = true;
		mapa[b-1][a-1] = true;
	}
	REP(i, n) bio.insert(i);
 	REP(i, n){
 		if(bio.count(i)){
 			sol++;
			dfs(i);
		 }
	}
	cout << sol-1 << endl;

}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
#define first x
#define second y
#define sd(x) scanf("%d",&x)
#define slld(x) scanf("%lld",&x)
#define ss(x) scanf("%s",x)
#define FOR(k,a,b) for(int k=(a); k<=(b); ++k)
#define REP(k,a) for(int k=0; k<(a);++k)
#define SZ(a) int((a).size())
#define ALL(c) (c).begin(),(c).end()
#define PB push_back
#define MP make_pair
#define INF 999999999
#define INFLONG 1000000000000000000
#define MOD 1000000007
#define MAX 100
#define ITERS 100
#define MAXM 200000
#define MAXN 1000000
#define _gcd __gcd
#define eps 1e-9

int n, v;
map<int, bool> mapa[100500];
int sol;
bool bio[100100];
void dfs(int x){

	if(bio[x]) return;
	bio[x] = true;
	REP(i, n){
		if(i != x && !bio[i]) {
			if(!mapa[x].count(i)) dfs(i);
		}
	}
	return;
}

int main(){

	cin >> n >> v;
	 ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	REP(i, v){
		int a, b;
		cin >> a >> b;
		mapa[a-1][b-1] = true;
		mapa[b-1][a-1] = true;
	}
 	REP(i, n){
 		if(!bio[i]){
 			sol++;
			dfs(i);
		 }

	}
	cout << sol-1 << endl;

}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

#define sd(x) scanf("%d",&x)
#define slld(x) scanf("%lld",&x)
#define ss(x) scanf("%s",x)
#define FOR(k,a,b) for(int k=(a); k<=(b); ++k)
#define REP(k,a) for(int k=0; k<(a);++k)
#define SZ(a) int((a).size())
#define ALL(c) (c).begin(),(c).end()
#define PB push_back
#define MP make_pair
#define INF 999999999
#define INFLONG 1000000000000000000
#define MOD 1000000007
#define MAX 100
#define ITERS 100
#define MAXM 200000
#define MAXN 1000000
#define _gcd __gcd
#define eps 1e-9

int n, v;
vector<set<int> > nule(100100);
set<int> sol;
bool bio[100100]; int disi[100100];
void dfs(int x, int idx){

	if(bio[x]) return;
	sol.insert(idx);
	bio[x] = true;
	REP(i, n){
		if(i != x && !bio[i]){
			set<int>::iterator it = nule[x].find(i);
			if(it == nule[x].end()) dfs(i, idx);

		}
	}
	return;
}

int main(){

	cin >> n >> v;

	REP(i, v){
		int a, b;
		cin >> a >> b;
		nule[a-1].insert(b-1);
		nule[b-1].insert(a-1);
	}
 	REP(i, n){
 		if(!bio[i]){
 			if(nule[i].size() == n-1){
 				sol.insert(i);
				 bio[i] = true;
 				continue;
			 }
 			dfs(i, i);
		 }
	}
	cout << sol.size()-1 << endl;

}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
#define first x
#define second y
#define sd(x) scanf("%d",&x)
#define slld(x) scanf("%lld",&x)
#define ss(x) scanf("%s",x)
#define FOR(k,a,b) for(int k=(a); k<=(b); ++k)
#define REP(k,a) for(int k=0; k<(a);++k)
#define SZ(a) int((a).size())
#define ALL(c) (c).begin(),(c).end()
#define PB push_back
#define MP make_pair
#define INF 999999999
#define INFLONG 1000000000000000000
#define MOD 1000000007
#define MAX 100
#define ITERS 100
#define MAXM 200000
#define MAXN 1000000
#define _gcd __gcd
#define eps 1e-9

int n, v;
vector<set<int> > nule(100100);
set<int> sol;
bool bio[100100];
void dfs(int x){

	if(bio[x]) return;
	bio[x] = true;
	REP(i, n){
		if(i != x && !bio[i]) {
			if(!nule[x].count(i)) dfs(i);
		}
	}
	return;
}

int main(){

	cin >> n >> v;
	 ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	REP(i, v){
		int a, b;
		cin >> a >> b;
		nule[a-1].insert(b-1);
		nule[b-1].insert(a-1);
	}
 	REP(i, n){
 		if(!bio[i]){
 			sol.insert(i);
			dfs(i);
		 }

	}
	cout << sol.size()-1 << endl;

}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

#define sd(x) scanf("%d",&x)
#define slld(x) scanf("%lld",&x)
#define ss(x) scanf("%s",x)
#define FOR(k,a,b) for(int k=(a); k<=(b); ++k)
#define REP(k,a) for(int k=0; k<(a);++k)
#define SZ(a) int((a).size())
#define ALL(c) (c).begin(),(c).end()
#define PB push_back
#define MP make_pair
#define INF 999999999
#define INFLONG 1000000000000000000
#define MOD 1000000007
#define MAX 100
#define ITERS 100
#define MAXM 200000
#define MAXN 1000000
#define _gcd __gcd
#define eps 1e-9

int n, v;
vector<set<int> > nule(100100);
set<int> sol;
bool bio[100100]; int disi[100100];
void dfs(int x, int idx){

	if(bio[x]) return;
	sol.insert(idx);
	bio[x] = true;
	REP(i, n){
		if(i != x && !bio[i]){
			set<int>::iterator it = nule[x].find(i);
			if(it == nule[x].end()) dfs(i, idx);

		}
	}
	return;
}

int main(){

	cin >> n >> v;

	REP(i, v){
		int a, b;
		cin >> a >> b;
		nule[a-1].insert(b-1);
		nule[b-1].insert(a-1);
	}
 	REP(i, n){
 		if(!bio[i]) dfs(i, i);
	}
	cout << sol.size()-1 << endl;

}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
#define first x
#define second y
#define sd(x) scanf("%d",&x)
#define slld(x) scanf("%lld",&x)
#define ss(x) scanf("%s",x)
#define FOR(k,a,b) for(int k=(a); k<=(b); ++k)
#define REP(k,a) for(int k=0; k<(a);++k)
#define SZ(a) int((a).size())
#define ALL(c) (c).begin(),(c).end()
#define PB push_back
#define MP make_pair
#define INF 999999999
#define INFLONG 1000000000000000000
#define MOD 1000000007
#define MAX 100
#define ITERS 100
#define MAXM 200000
#define MAXN 1000000
#define _gcd __gcd
#define eps 1e-9

int n, v;
map<int, bool> mapa[100500];
int sol;
bool bio[100100];
void dfs(int x){

	if(bio[x]) return;
	bio[x] = true;
	REP(i, n){
		if(i != x && !bio[i]) {
			if(!mapa[x].count(i)) dfs(i);
		}
	}
	return;
}

int main(){

	cin >> n >> v;

	REP(i, v){
		int a, b;
		cin >> a >> b;
		mapa[a-1][b-1] = true;
		mapa[b-1][a-1] = true;
	}
 	REP(i, n){
 		if(!bio[i]){
 			sol++;
			dfs(i);
		 }

	}
	cout << sol-1 << endl;

}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
#define first x
#define second y
#define sd(x) scanf("%d",&x)
#define slld(x) scanf("%lld",&x)
#define ss(x) scanf("%s",x)
#define FOR(k,a,b) for(int k=(a); k<=(b); ++k)
#define REP(k,a) for(int k=0; k<(a);++k)
#define SZ(a) int((a).size())
#define ALL(c) (c).begin(),(c).end()
#define PB push_back
#define MP make_pair
#define INF 999999999
#define INFLONG 1000000000000000000
#define MOD 1000000007
#define MAX 100
#define ITERS 100
#define MAXM 200000
#define MAXN 1000000
#define _gcd __gcd
#define eps 1e-9

int n, v;
map<int, bool> mapa[100500];
int sol;
bool bio[100100];
void dfs(int x){

	if(bio[x]) return;
	bio[x] = true;
	FOR(i, x+1, n){
		if(!bio[i]) {
			if(!mapa[x].count(i)) dfs(i);
		}
	}
	return;
}

int main(){

	cin >> n >> v;

	REP(i, v){
		int a, b;
		cin >> a >> b;
		mapa[a-1][b-1] = true;
		mapa[b-1][a-1] = true;
	}
 	REP(i, n){
 		if(!bio[i]){
 			sol++;
			dfs(i);
		 }

	}
	cout << sol-1 << endl;

}


#include<bits/stdc++.h>
#include<bits/stdc++.h>
#include <vector>
#define ll long long int
#define ve vector<int>
#define vell vector<ll>
#define ve_pa vector<pair<ll,ll> >
#define pb push_back
#define mod 1000000007
#define ld long double
#define pii pair<int,int>
#define pll pair<ll,ll>
#define fi first
#define se second
using namespace std;
int n,m;
map<int,bool>u[200005];
bitset<2000005>bit;

void dfs(int s)
{
	bit[s]=0;
	for(int i=bit._Find_first();i<bit.size();i=bit._Find_next(i))
	{
		if(!u[s][i])
		{
			dfs(i);
		}
	}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin>>n>>m;
for(int i=0;i<m;i++)
{
	int x,y;cin>>x>>y;
	u[x][y]=1;
	u[y][x]=1;
}
int ans=0;
for(int i=1;i<=n;i++)
bit[i]=1;

for(int i=1;i<=n;i++)
{
	if(bit[i])
	{
		dfs(i);
		ans++;
	}
}
cout<<ans-1;

}


#include<bits/stdc++.h>
#include<bits/stdc++.h>
#include <vector>
#define ll long long int
#define ve vector<int>
#define vell vector<ll>
#define ve_pa vector<pair<ll,ll> >
#define pb push_back
#define mod 1000000007
#define ld long double
#define pii pair<int,int>
#define pll pair<ll,ll>
#define fi first
#define se second
using namespace std;
map<int,int>g[200005];
bitset<200005> v;
void dfs(int s)
{
	v[s]=0;
	for(int i=v._Find_first();i<v.size();i=v._Find_next(i))
	{
		if(g[s][i]==0)
		{
			dfs(i);
		}
	}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int n,m;cin>>n>>m;
for(int i=0;i<m;i++)
{
	int u,v;cin>>u>>v;
	g[u][v]=1;
	g[v][u]=1;
}
int ans=0;
for(int i=1;i<=n;i++)
v[i]=1;

for(int i=1;i<=n;i++)
{
	if(v[i])
	{
		dfs(i);
		ans++;
	}
}
cout<<ans-1;

}


#include<bits/stdc++.h>
#include<bits/stdc++.h>
#include <vector>
#define ll long long int
#define ve vector<int>
#define vell vector<ll>
#define ve_pa vector<pair<ll,ll> >
#define pb push_back
#define mod 1000000007
#define ld long double
#define pii pair<int,int>
#define pll pair<ll,ll>
#define fi first
#define se second
using namespace std;
int n,m;
map<int,bool>u[200005];
bitset<2000005>bit;
void dfs(int v){
	bit[v]=0;
	for(int i=bit._Find_first();i<bit.size();i=bit._Find_next(i)) if(!u[v][i])dfs(i);
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin>>n>>m;
for(int i=0;i<m;i++)
{
	int x,y;cin>>x>>y;
	u[x][y]=u[y][x] =1;
}
int ans=0;
for(int i=1;i<=n;i++)
bit[i]=1;

for(int i=1;i<=n;i++)
{
	if(bit[i])
	{
		dfs(i);
		ans++;
	}
}
cout<<ans-1;

}