/*
 * Author : Siddhant Khare
 */
#include <bits/stdc++.h>
using namespace std;

/*******  All Required define Pre-Processors and typedef Constants *******/
#define ll long long
#define ld long double
#define arr array
#define si(t) scanf("%d", &t)
#define sl(t) scanf("%ld", &t)
#define sll(t) scanf("%lld", &t)
#define sc(t) scanf("%c", &t)
#define ss(t) scanf("%s", &t)
#define sf(t) scanf("%f", &t)
#define slf(t) scanf("%lf", &t)
#define pi(x) printf("%d\n", x)
#define pl(x) printf("%ld\n", x)
#define pll(x) printf("%lld\n", x)
#define pf(x) printf("%f")
#define sz(x) (int)(x).size()
#define mem(a, b) memset(a, (b), sizeof(a))
#define FOR(i, j, k, in) for (int i = j; i < k; i += in)
#define RFOR(i, j, k, in) for (int i = j; i >= k; i -= in)
#define REP(i, j) FOR(i, 0, j, 1)
#define RREP(i, j) RFOR(i, j, 0, 1)
#define all(x) x.begin(), x.end()
#define rall(cont) cont.end(), cont.begin()
#define FOREACH(it, l) for (auto it = l.begin(); it != l.end(); it++)
#define IN(A, B, C) assert(B <= A && A <= C)
#define sortall(x) sort(all(x))
#define mp make_pair
#define pb push_back
#define INF (int)1e9
#define EPS 1e-9
#define PI 3.1415926535897932384626433832795
#define MOD 1000000007
#define read(type) readInt<type>()
const double pi = acos(-1.0);
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<PII> VII;
typedef vector<VI> VVI;
typedef map<int, int> MPII;
typedef set<int> SETI;
typedef multiset<int> MSETI;

/**************************************/

/******** User-defined Function *******/
void solve()
{
    ll n;
    cin >> n;
    ll a[n], b[n];
    set<ll> st;
    for (ll i = 0; i < n; i++)
    {
        cin >> a[i] >> b[i];
        st.insert(a[i]);
        st.insert(b[i]);
    }
    cout << st.size() << "\n";
    // Algorithm

    // Output
    // pll(ans) // long long print
}

/**************************************/

/********** Main()  function **********/
ll prt[400001];
ll find_set(ll v)
{
    if (v == prt[v])
        return v;
    return find_set(prt[v]);
}

void union_sets(ll a, ll b)
{
    a = find_set(a);
    b = find_set(b);
    if (a != b)
        prt[b] = a;
}

signed main()
{
    ll n, a, b;
    cin >> n;
    set<ll> res;
    for (ll i = 0; i <= 400000; i++)
        prt[i] = i;
    map<ll, vector<ll>> v;
    for (ll i = 0; i < n; i++)
    {
        cin >> a >> b;
        if (a > b)
            swap(a, b);
        v[a].push_back(b);
    }
    for (auto i : v)
    {
        for (auto j : i.second)
        {
            if (res.find(find_set(j)) == res.end())
                res.insert(find_set(j)), union_sets(i.first, j);
            else
                res.insert(find_set(i.first));
        }
    }
    cout << res.size() << endl;
}
/********  Main() Ends Here *************/

//#pragma GCC target("avx2")
//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma warning(disable : 4996)
//
////#define ATCODER
//#ifdef ATCODER
//#include<atcoder/all>
//using namespace atcoder;
//#endif


#include <algorithm>
#include <utility>
#include <vector>
#include <limits.h>
#include <math.h>
#include <time.h>
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <complex>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <cassert>
#include <numeric>
#include <type_traits>

using namespace std;



#ifdef _MSC_VER
#include"stdafx.h"
#include <intrin.h>
#define __builtin_popcount __popcnt
#define __builtin_popcountll __popcnt64
void debug_out() { cerr << endl; }

template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	cerr << " " << (H);
	debug_out(T...);
}
#define DEBUG(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define DEBUG(...) 42
#endif



#define ll long long
#define REP(i, n) for (ll i = 0; i < (n); ++i)
#define REPR(i, n) for (ll i = (n) - 1; i >= 0; --i)
#define FOR(i, m, n) for (ll i = (m); i < (n); ++i)
#define VSORT(v) sort(v.begin(), v.end());
#define VREVERSE(v) reverse(v.begin(), v.end())

#define print(x) cout << (x) << '\n'
#define spa <<" "<<
#define lb(v, n) lower_bound(v.begin(), v.end(), (n))
#define ub(v, n) upper_bound(v.begin(), v.end(), (n))
//#define int long long
//#define double long double
#define all(x) (x).begin(), (x).end()
#define print_space(v) REP(i, v.size()) cout << v[i] << " \n"[i==(int)v.size()-1]
template <typename T1, typename T2> inline bool chmin(T1 & a, T2 b) { if (a > b) { a = b; return true; }return false; }
template <typename T1, typename T2> inline bool chmax(T1& a, T2 b) { if (a < b) { a = b; return true; }return false; }
typedef pair<int, int> pii;
typedef pair<long long, long long> pll;
std::random_device rd;
std::mt19937 mt(rd());
constexpr ll MOD = 1e9 + 7;
constexpr int MAX = 400040;
const double pi = acos(-1);
constexpr long double EPS = 1e-14;
const int dx[4] = { 0,0,-1,1 }, dy[4] = { -1,1,0,0 };
using ld = long double;


bool G[20][20];
int INF = 1e9;
int dp[1 << 18];
int N;
bool possible[1 << 18];
int ans = INF;
int rec(int bit) {
	if (dp[bit] != INF)return dp[bit];
	int n = __builtin_popcountll(bit);

	if (n == 0)return dp[n] = 0;
	if (possible[bit])return dp[bit] = 1;
	vector<int>id(n);
	int idx = 0;
	REP(i, N) {
		if (bit >> i & 1)id[idx++] = i;
	}
	int ret = n;
	for (int nbit = bit;; nbit = (nbit - 1)&bit) {
		if (nbit == bit)continue;
		if (nbit == 0)break;
		ret = min(ret, rec(nbit) + rec(bit^nbit));
		
	}
	//for (int k = n-1; k >= 1; k--) {
	//	vector<int>p(n);
	//	FOR(i, n - k, n)p[i] = true;
	//	do {
	//		int bb = 0;
	//		REP(i, n) {
	//			if (p[i])bb |= 1 << id[i];
	//		}
	//		int bbb = bit ^ bb;
	//		ret = min(ret, rec(bb) + rec(bbb));
	//	} while (next_permutation(all(p)));
	//}
	//
	//DEBUG(b, ret);
	return dp[bit] = ret;
}

void solve() {
	cin >> N;
	int M; cin >> M;
	REP(i, 1 << N)dp[i] = INF;

	if (M == 0) {
		print(N);
		return;
	}
	REP(i, M) {
		int u, v; cin >> u >> v;
		u--, v--;
		G[u][v] = G[v][u] = true;
	}


	REP(i, N)G[i][i] = true;
	REP(bit, 1 << N) {
		int n = __builtin_popcount(bit);
		if (n <= 1)possible[bit] = true;
		bool ok = true;
		REP(i, N) {
			if (bit >> i & 1) {
				FOR(j, i + 1, N) {
					if (bit >> j & 1) {
						if (!G[i][j]) {
							ok = false;
							break;
						}
					}
				}
			}
		}
		if (ok)possible[bit] = true;
	}
	//print(1); return;
	ans = INF;
	int bit = 0;
	REP(i, N)bit |= 1 << i;
	print(rec(bit));
}

signed main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	//int q; cin >> q;
	//while (q--)
	solve();
}