#include <bits/stdc++.h>
using namespace std;
using ll = long long;

#define cm (1 << 17)
char cn[cm], *ci = cn + cm, ct;

inline char getcha() {
	if (ci - cn == cm) {
		fread(cn, 1, cm, stdin);
		ci = cn;
	}
	return *ci++;
}

inline int getint() {
	int A = 0;
	while ((ct = getcha()) >= '0') A = A * 10 + ct - '0';
	return A;
}

static struct FastOutput {
	static constexpr int BUF_SIZE = 1 << 20;
	char buf[BUF_SIZE];
	size_t buf_pos = 0;
	static constexpr int TMP_SIZE = 1 << 20;
	char tmp[TMP_SIZE];
	FILE* out = stdout;

	inline void put_char(char c) {
		buf[buf_pos++] = c;
		if (buf_pos == BUF_SIZE) {
			fwrite(buf, 1, buf_pos, out);
			buf_pos = 0;
		}
	}

	~FastOutput() { fwrite(buf, 1, buf_pos, out); }

	inline FastOutput& operator<<(char c) {
		put_char(c);
		return *this;
	}

	inline FastOutput& operator<<(const char* s) {
		while (*s) {
			put_char(*s++);
		}
		return *this;
	}

	inline FastOutput& operator<<(const string& s) {
		for (int i = 0; i < (int)s.size(); i++) {
			put_char(s[i]);
		}
		return *this;
	}

	template <typename T>
	inline char* integer_to_string(T n) {
		// beware of TMP_SIZE
		char* p = tmp + TMP_SIZE - 1;
		if (n == 0) {
			*--p = '0';
		} else {
			bool is_negative = false;
			if (n < 0) {
				is_negative = true;
				n = -n;
			}
			while (n > 0) {
				*--p = (char)('0' + n % 10);
				n /= 10;
			}
			if (is_negative) {
				*--p = '-';
			}
		}
		return p;
	}

	template <typename T>
	inline typename enable_if<is_integral<T>::value, char*>::type stringify(T n) {
		return integer_to_string(n);
	}

#if !defined(_WIN32) || defined(_WIN64)
	inline char* stringify(__int128 n) { return integer_to_string(n); }
#endif

	template <typename T>
	inline typename enable_if<is_floating_point<T>::value, char*>::type stringify(T n) {
		sprintf(tmp, "%.17f", n);
		return tmp;
	}

	template <typename T>
	inline FastOutput& operator<<(const T& n) {
		auto p = stringify(n);
		for (; *p != 0; p++) {
			put_char(*p);
		}
		return *this;
	}
} fast_output;

#define cout fast_output

vector<int> p;

int get(int x) {
	return p[x] == -1 ? x : p[x] = get(p[x]);
}

int main() {
	int n = getint();
	constexpr int mx = 400010;
	p.resize(mx, -1);
	vector<int> cnt(mx);
	while (n--) {
		int a = getint(), b = getint();
		a = get(a), b = get(b);
		if (a != b) {
			p[b] = a;
			cnt[a] += cnt[b];
		}
		cnt[a]++;
	}
	vector<int> siz(mx);
	for (int i = 0; i < mx; i++) {
		siz[get(i)]++;
	}
	int ans = 0;
	for (int i = 0; i < mx; i++) {
		if (get(i) == i) {
			ans += min(cnt[i], siz[i]);
		}
	}
	cout << ans;
}

#include    <bits/stdc++.h>
#define fo(i,a,b) for(int i=(a);i<=(b);++i)
#define __unique(V) (V).resize(unique((V).begin(),(V).end())-(V).begin())
#define cntbit(X)   __builtin_popcount((X))
#define bit(S,i) (((S)>>(i - 1))&1)
#define PI	acos(-1)
#define fi  first
#define se  second
#define LL  long long
#define ii  pair<int,int>
#define iii pair<int,ii>
#define eb  emplace_back
#define TASK "abc187"
using namespace std;
const int maxn = 20;
int n,m,g[1 << maxn];
bool a[maxn][maxn],dp[1 << maxn];
///--------------------------
void    readf(){
    cin >> n >> m;
    for(int i = 1; i <= m; ++i){
        int u,v;
        cin >> u >> v;
        a[u][v] = 1;
    }
}
///--------------------------
void    solve(){
    for(int mask = 0; mask < (1 << n); ++mask){
        for(int i = 1; i <= n; ++i) if (bit(mask,i))
        for(int j = i + 1; j <= n; ++j) if (bit(mask,j)){
            if (a[i][j] == 0) goto nxt;
        }
        dp[mask] = 1;
        nxt : ;
    }
    memset(g,0x3f,sizeof(g));
    g[0] = 0;
    for(int mask = 1; mask < (1 << n); ++mask)
    for(int i = mask; i > 0; i = (i - 1) & mask) if (dp[i] == 1){
        g[mask] = min(g[mask],g[mask ^ i] + 1);
    }
    cout << g[(1 << n) - 1] << '\n';
}
///--------------------------
int     main(){
	srand(time(NULL));
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    #ifdef TLH2203
        freopen(TASK".inp", "r", stdin);
        freopen(TASK".out", "w", stdout);
    #endif // TLH2203
    readf();
    solve();
}




