#include <bits/stdc++.h>

#define ull unsigned ll
#define ll long long int
#define ld long double
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define ff first
#define ss second
#define pi acos(-1)
#define nu 100
#define INF 100000000000
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization ("unroll-loops")
#define F(i,a,n) for(ll i=a;i<n;i++)
#define B(i,a,n) for(ll i=n-1;i>=a;i--)

#define tc int t;cin>>t;while(t--)
#define tcf ll t;cin>>t;for(int w=1;w<=t;w++)

const int mod = 1000000007;


using namespace std;


ll binpow(ll a, ll b)
{
    ll res = 1;
    while (b > 0)
    {
        if (b & 1)
        {
            res = (res * a);
        }
        a = (a * a);
        b >>= 1;
    }
    return res;
}


void dex(int a)
{
    if (a == 1)
        cout << "1\n";
    else if (a == -1)
        cout << "-1\n";
    else if (a == 0)
        cout << "0\n";
    else if (a == 2)
        cout << "YES\n";
    else if (a == 3)
        cout << "NO\n";
    else if (a == 4)
        cout << "yes\n";
    else if (a == 5)
        cout << "no\n";
}

ll fermat_inv(ll y) {return binpow(y, mod - 2);}
ll fact[100005];
ll finv[100005];
void factorial(int n) {
    fact[0] = 1;
    finv[0] = 1;
    for (int i = 1; i <= n; i++)
        fact[i] = fact[i - 1] * i, fact[i] %= mod, finv[i] = fermat_inv(fact[i]);
}
ll ncr(ll n, ll r)
{
    if (n < r)
        return 0;
    else {
        ll x = finv[r] * finv[n - r] % mod;
        return fact[n] * x % mod;
    }
}
bool prime[10000001];
void seive()
{
    memset(prime, 1, sizeof(prime));
    for (ll i = 2; i * i <= 10000001; i++)
    {
        if (prime[i] == 1)
        {
            for (ll j = i * i; j <= 10000001 ; j += i)
            {
                prime[j] = 0;
            }
        }
    }

}

//Polynomial Rolling Hash function\\

const int MOD = 1e9 + 9;
const int p_o = 53;
vector<ll>p_pow;
void ffpow(ll n)
{

    p_pow.resize(n);
    p_pow[0] = 1;
    F(i, 1, n)
    {
        p_pow[i] = (p_pow[i - 1] * p_o) % MOD;
    }
}
ll Hash(string const&s)
{
    ll res = 0;
    ll j = 0;
    for (auto i : s)
    {
        res += (((i - 'a' + 1) % MOD) * (p_pow[j] % MOD)) % MOD;
        j++;
    }
    return res;
}


vector<ll>adj[100005];
vector<ll>vis(100005, 0);
vector<ll>R(100005, 0);
vector<ll>par(100005);
vector<ll>col(100005);
ll r = 0;
void dfs(ll node)
{
    r++;
    vis[node] = 1;
    for (auto i : adj[node])
    {
        if (!vis[i])
        {
            par[i] = node;
            dfs(i);
        }
    }
}

int Find(int x)
{
    if (par[x] < 0)
        return x;
    return par[x] = Find(par[x]);
}
void Union(int x, int y)
{
    if (R[x] > R[y])
    {
        par[x] += par[y];
        R[x] += R[y];
        par[y] = x;
    }
    else
    {
        par[y] += par[x];
        R[y] += R[x];
        par[x] = y;
    }
}

int main()
{

#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    /*tc{
        ll n;
        cin>>n;
        ll a[n];
        map<ll,ll>m;
        F(i,0,n)
        {
            cin>>a[i];
            m[a[i]]++;
        }
        ll ans=0;
        for(int i=0;i<=n;i++)
        {
            if(!m[i])
            {
                m[i]++;
                ans+=i;
            }
        }
        for(int i=0;i<=n)
    }*/
    ll n, e;
    cin >> n >> e;
    ll x, y;
    F(i, 0, e)
    {
        cin >> x >> y;
        adj[x].pb(y);
        adj[y].pb(x);
    }
    ll ct = 0;
    ll sum = 0;
    F(i, 1, n + 1)
    {
        r = 0;
        if (!vis[i])
        {
            dfs(i);
            ct++;
        }
        if (r == 1)
        {
            sum++;
        }
    }
    cout << ct - 1 << "\n";


    return 0;

}

Measured memory_bytes: 12912