//#include <bits/stdc++.h>
#include <iostream>
#include <vector>
#include <unordered_map>
#include <cstring>
#include <climits>
#include <algorithm>
#include <set>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>
#include <queue>
#include <iomanip>
#include <map>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#pragma comment(linker, "/STACK: 2000000")
/*#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>*/
using namespace std;
// using namespace __gnu_pbds;
/*template <typename T> 
using ordered_set = tree< T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;*/
/*===================================================================================================================
===================================================================================================================*/
									// Debugging
void __print(int x) {cerr << x;}
void __print(long x) {cerr << x;}
void __print(long long x) {cerr << x;}
void __print(unsigned x) {cerr << x;}
void __print(unsigned long x) {cerr << x;}
void __print(unsigned long long x) {cerr << x;}
void __print(float x) {cerr << x;}
void __print(double x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << '\'' << x << '\'';}
void __print(const char *x) {cerr << '\"' << x << '\"';}
void __print(const string &x) {cerr << '\"' << x << '\"';}
void __print(bool x) {cerr << (x ? "true" : "false");}
template<typename T, typename V> void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ','; __print(x.second); cerr << '}';}
template<typename T> void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), __print(i); cerr << "}";} void _print() {cerr << "]\n";}
template <typename T, typename... V> void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
#ifndef ONLINE_JUDGE
#define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
#define debug(x...)
#endif
/*===================================================================================================================
===================================================================================================================*/
							// Macros
#define ll 	 long long int
#define ld   long double
// #define mod  100000007
#define REP(i, n) for(int i = 0; i < (n); i++)
#define INF  INT_MAX
#define mp   make_pair
#define pb   push_back
#define eb   emplace_back
#define PHI  1000001
#define sz(x) (int)(x).size()
#define speed ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define sum(a)     ( accumulate ((a).begin(), (a).end(), 0ll))
#define mine(a)    (*min_element((a).begin(), (a).end()))
#define maxe(a)    (*max_element((a).begin(), (a).end()))
#define mini(a)    ( min_element((a).begin(), (a).end()) - (a).begin())
#define maxi(a)    ( max_element((a).begin(), (a).end()) - (a).begin())
#define lowb(a, x) ( lower_bound((a).begin(), (a).end(), (x)) - (a).begin())
#define uppb(a, x) ( upper_bound((a).begin(), (a).end(), (x)) - (a).begin())
#define exectime() cerr << '\n' <<"execution time " << (double)(clock() - tStart)/CLOCKS_PER_SEC << "\n";
/*===================================================================================================================
===================================================================================================================*/
							//Read array, pair

template<typename T>             istream& operator>>(istream& is,  vector<T>& v){for (auto& i : v) is >> i;        return is;}
template<typename T>             ostream& operator<<(ostream& os,  vector<T>& v){for (auto& i : v) os << i << ' '; return os;}
template<typename T, typename U> istream& operator>>(istream& is, pair<T, U>& p){is >> p.first >> p.second;        return is;}
template<typename T, typename U> ostream& operator<<(ostream& os, pair<T, U>& p){os << p.first << ' ' << p.second; return os;}

/*===================================================================================================================
===================================================================================================================*/
							//Math

inline ll ce(ll a,ll b){return (a%b==0?a/b:a/b+1);}
inline ll powm(ll b,ll p,ll m){b%=m;if (b==0){return 0;}ll ans=1;while (p>0){if (p%2==1){ans=(ans*b)%m;}p/=2;b=(b*b)%m;}return ans;}
inline ll gcd(ll a, ll b){if(b == 0) {return a;} return gcd(b, a%b);}
inline ll lcm(ll a, ll b){return ((a*b)/gcd(a, b));}
inline bool ispow2(int x){return (x!=0 && (x&(x-1))==0);}
inline bool isprime(ll n){if (n==0||n==1){return 0;}else if (n==2||n==3){return 1;}if (n%2==0){return 0;}ll t=floor(sqrt(n));for (ll i=3; i<=t; i+=2){if (n%i==0){return 0;}}return 1;}
inline ll ncr(ll n,ll r){if (n<r){return 0;}ll ans=1;ll k=min(n-r,r);for (ll i=1; i<=k; i++){ans=ans*(n-i+1)/i;}return ans;}
inline ll fib(ll n){const ld r5=sqrt(5);const ld ra=(r5+1)/2;return round(pow(ra,n)/r5);}
ll phi[PHI];
inline void totient(){for(int i=1;i<PHI; i++)phi[i]=(i&1)?i:i/2;for(ll i=3;i<PHI;i+=2)if(phi[i]==i)for(ll j=i;j<PHI;j+=i)phi[j]-=phi[j]/i;}
int spf[1000001];
inline void find_spf(){ ll n = 1000000; for(ll i = 1; i <= n; i++) spf[i] = i;for(ll i = 2; i <= n; i++){for(ll j = i*i; j <= n; j+=i){if(spf[j] == j){spf[j] = i;}}}}
unordered_map<int, int> find_pf(int n)
{
	unordered_map<int, int> pf;
	while(n != 1)
		{pf[spf[n]]++;n /= spf[n];}
	return pf;
}
/*====================================================================================================================
====================================================================================================================*/
							// Code Begins

const int N = 1e5+5;
vector<int> adj[N];

bool visited[N];
int parent[N];
int ranks[N];


int find(int node)
{
	if(parent[node] == -1)
		return node;
	return parent[node] = find(parent[node]);
}

void Union(int a, int b)
{
	if(ranks[a] < ranks[b])
	{
		parent[a] = b;

	}
	else if(ranks[a] > ranks[b])
	{
		parent[b] = a;
	}
	else
	{
		parent[b] = a;
		ranks[a]++;
	}
}
int32_t main() {
	int n, m;
	cin >> n >> m;

	memset(visited, false, sizeof(visited));
	memset(parent, -1, sizeof(parent));
	int cnt = 0;
	for(int i = 0; i < m; i++)
	{
		int a, b;
		cin >> a >> b;
		a--, b--;
		adj[a].push_back(b);
		adj[b].push_back(a);
		int x  = find(a);
		int y = find(b);

		if(x == y)
		{
			cnt++;
		}
		else
		{
			Union(x, y);
		}
	}
	m -= cnt;

	cout << max(0, n-m-1) << '\n';
	
}




Measured memory_bytes: 9572