#include <bits/stdc++.h>
#define int long long int
#define pb push_back
#define Pii pair<int,int>
#define SS second 
#define F first
#define mod 1000000007
#define ld long double
#define sp fixed<<setprecision(12)
using namespace std;
#define db(...) __f(#__VA_ARGS__, __VA_ARGS__)

template <typename Arg1>
void __f(const char* name, Arg1&& arg1) { cout << name << " : " << arg1 << '\n'; }
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args) {
    const char* comma = strchr(names + 1, ',');
    cout.write(names, comma - names) << " : " << arg1 << " | "; __f(comma + 1, args...);
}

struct dsu {
    vector<int> par;
    vector<int> rnk;
    vector<int> sz;

    void init(int n){
        par.resize(n);
        rnk.resize(n);
        sz.resize(n);
        for(int i=0;i<n;i++){
            par[i]=i;
            rnk[i]=0;
            sz[i]=1;
        }
    }

   int findpar(int node ){
        if(node == par[node])
            return node;
        return par[node] = findpar(par[node]);
    }

    void unite(int u ,int v){
        int p1 = findpar(u);
        int p2 = findpar(v);
        if(p1!=p2)
        {
            int r1 = rnk[p1];
            int r2 = rnk[p2];
            if(r1 < r2)
            {
                par[p1] = p2;
                sz[p2]+=sz[p1];
                sz[p1]=0;
                rnk[p2]++;
            }
            else
            {
               par[p2] = p1;
               sz[p1]+=sz[p2];
               sz[p2]=0;
               rnk[p1]++;
            }
        }
    }

} G;


void solve(){
    int n,m;
    cin>>n>>m;
    G.init(n+1);
    for(int i=0;i<m;i++){
        int x,y;
        cin>>x>>y;
        G.unite(x,y);
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        int p=G.findpar(i);
        if(i==p){
            ans++;
        }
    }
    cout<<(ans-1)<<'\n';

}


int32_t main(){

    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
    #endif
    //double    pi=3.14159265358979323846;
    //sieve();
    int t=1;
    //cin>>t;
    while(t--){
        solve();
    }
    
    return 0;
    
}//Ardhendu Reja , JGEC

/*
int powmod(int x,int n,int p)
{
    int result=1;
    while(n>0)
    {
        if(n % 2 ==1)
            result=(result * x)%p;
        x=(x*x)%p;
        n=n/2;
    }
    return result;
}


int modmul(int a,int b) {
    return ((a % mod) * (b % mod)) % mod;
}
*/

//const int N=200005;
/*
struct dsu {
    vector<int> par;
    vector<int> rnk;
    vector<int> sz;

    void init(int n){
        par.resize(n+1);
        rnk.resize(n+1);
        sz.resize(n+1);
        for(int i=0;i<=n;i++){
            par[i]=i;
            rnk[i]=0;
            sz[i]=1;
        }
    }

   int findpar(int node ){
        if(node == par[node])
            return node;
        return par[node] = findpar(par[node]);
    }

    void unite(int u ,int v){
        int p1 = findpar(u);
        int p2 = findpar(v);
        if(p1!=p2)
        {
            int r1 = rnk[p1];
            int r2 = rnk[p2];
            if(r1 < r2)
            {
                par[p1] = p2;
                sz[p2]+=sz[p1];
                sz[p1]=0;
                rnk[p2]++;
            }
            else
            {
               par[p2] = p1;
               sz[p1]+=sz[p2];
               sz[p2]=0;
               rnk[p1]++;
            }
        }
    }

} G;
*/


Measured memory_bytes: 5552