//#include <atcoder/all>
#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp> 
// #include <ext/pb_ds/tree_policy.hpp> 
using namespace std;
//using namespace atcoder;
//using namespace __gnu_pbds;
 
 
/* -------------------------    Debug template   ---------------------*/
vector<string> split(const string& s, char c) {
    vector<string> v; stringstream ss(s); string x;
    while (getline(ss, x, c)) v.emplace_back(x); return move(v);
}
template<typename T, typename... Args>
inline string arrStr(T arr, int n) {
    stringstream s; s << "[";
    for(int i = 0; i < n - 1; i++) s << arr[i] << ",";
    s << arr[n - 1] << "]";
    return s.str();
}
 
#define EVARS(args...) {__evars_begin(__LINE__); __evars(split(#args, ',').begin(), args);}
 
inline void __evars_begin(int line) { cerr << "#" << line << ": "; }
template<typename T> inline void __evars_out_var(vector<T> val) { cerr << arrStr(val, val.size()); }
template<typename T> inline void __evars_out_var(T* val) { cerr << arrStr(val, 10); }
template<typename T> inline void __evars_out_var(T val) { cerr << val; }
inline void __evars(vector<string>::iterator it) { cerr << endl; }
 
template<typename T, typename... Args>
inline void __evars(vector<string>::iterator it, T a, Args... args) {
    cerr << it->substr((*it)[0] == ' ', it->length()) << "=";
    __evars_out_var(a);
    cerr << "; ";
    __evars(++it, args...);
}
/* -------------------------    Debug template end   Used with EVARS()---------------------*/
 
 
#define ll long long
#define fr(i,a,b) for (ll i = (a), _b = (b); i <= _b; i++)
#define frr(i,a,b) for (ll i = (b), _a = (a); i >= _a; i--)
#define rep(i,n) for (ll i = 0, _n = (n); i < _n; i++)
#define repr(i,n) for (ll i = (n) - 1; i >= 0; i--)
#define all(ar) ar.begin(), ar.end()
#define rall(ar) ar.rbegin(), ar.rend()
#define sz(x) ((long long)x.size())
#define pb push_back
#define pob pop_back()
#define pf push_front
#define pof pop_front()
#define mp make_pair
#define ff first
#define ss second
#define trace(x) cout<<#x<<": "<<x<<endl;
#define trace2(x, y)            cout <<#x<<": "<<x<<" | "<<#y<<": "<<y<< endl;
#define trace3(x, y, z)         cout <<#x<<": "<<x<<" | "<<#y<<": "<<y<<" | "<<#z<<": "<<z<<endl;
#define trace4(a, b, c, d)      cout <<#a<<": "<<a<<" | "<<#b<<": "<<b<<" | "<<#c<<": "<<c<<" | "<<#d<<": "<<d<<endl;
#define trace5(a, b, c, d, e)   cout <<#a<<": "<<a<<" | "<<#b<<": "<<b<<" | "<<#c<<": "<<c<<" | "<<#d<<": "<<d<<" | "<<#e<<": "<<e<<endl;
#define trace6(a, b, c, d, e, f)cout <<#a<<": "<<a<<" | "<<#b<<": "<<b<<" | "<<#c<<": "<<c<<" | "<<#d<<": "<<d<<" | "<<#e<<": "<<e<<" | "<<#f<<": "<<f<<endl;
 
//typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ost;
typedef pair<ll, ll> ii;
typedef pair<ll, ii> iii;
typedef vector<ii> vii;
typedef vector<ll> vi;
typedef vector<string> vs;
typedef vector<vi> vvi;
 
 
const int d4i[4]={-1, 0, 1, 0}, d4j[4]={0, 1, 0, -1};
const int d8i[8]={-1, -1, 0, 1, 1, 1, 0, -1}, d8j[8]={0, 1, 1, 1, 0, -1, -1, -1};
 
ll gcd(ll a, ll b){
    if(b==0)
        return a;
    return gcd(b,a%b);
}
 
ll lcm(ll a, ll b){
	return ((a*b)/gcd(a,b));
}
 
ll modpower(ll base,ll power,ll mod){
	if(base==0||base==1)return base;
	ll res=1;
	while(power){
		if(power%2){
			res=(res*base)%mod;
			power--;
		}
		base=(base*base)%mod;
		power/=2;
	}
	return (res+mod)%mod;
}
 
 
ll const INF=1LL<<60LL;
double const pi=3.14159265358979323846264338327950; 
 
ll const MAX=1e5+1;
ll mod =998244353;
ll n,m;
vi g[MAX];
ll vis[MAX];

void dfs(ll u){
	vis[u]=1;
	for(auto v:g[u]){
		if(vis[v]==0)dfs(v);
	}
}
void solve(){
	cin>>n>>m;
	rep(i,m){
		ll x,y;
		cin>>x>>y;
		g[x].pb(y);
		g[y].pb(x);
	}
	ll cnt=0;
	fr(i,1,n){
		if(vis[i]==0){
			dfs(i);
			cnt++;
		}
	}

	cout<<cnt-1<<endl;
    
}
 
int main ()     
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout<<setprecision(30);
    #ifndef ONLINE_JUDGE
    freopen("inputf.in", "r", stdin);
    freopen("outputf.in", "w", stdout);
    #endif
 
    ll t=1;
    //cin>>t;
 
    while(t--){
    	// cout<<"Case #"<<i<<": ";
        solve();
 
    }
 
    return 0;   
}

Measured memory_bytes: 11084