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

#define llong long long 
#define len(x) ((int)x.size())
#define rep(i,n) for (int i = -1; ++ i < n; )
#define rep1(i,n) for (int i = 0; i ++ < n; )
#ifdef testing/*{{{*/
mt19937 rng(177013);
#else
mt19937 rng(chrono::system_clock::now().time_since_epoch().count());
#endif
#define rand() (int)(rng() >> 1)
#define CONCAT_(x, y) x##y
#define CONCAT(x, y) CONCAT_(x, y)
#define SPEC(name) CONCAT(name, __LINE__)
#ifdef LOCAL_DEBUG   
int __db_level = 0;
#define clog cerr << string(__db_level * 2, ' ')
struct debug_block {
    string msg;
    debug_block(const string& s): msg(s) { clog << "{ " << msg << endl; ++__db_level; }
    ~debug_block() { --__db_level; clog << "} " << msg << endl; }
};
#define DB(args...) stringstream SPEC(ss); SPEC(ss)<< args; debug_block SPEC(dbbl)(SPEC(ss).str())
#else
#define clog if (0) cerr
#define DB(...)
#endif
#define db(val) "[" #val " = " << val << "]; "
template<class U, class V> ostream& operator<<(ostream& out, const pair<U, V>& p) {
    return out << "(" << p.first << ", " << p.second << ")";
}
template<size_t i, class T> ostream& print_tuple_utils(ostream& out, const T& tup) {
    if constexpr(i == tuple_size<T>::value) return out << ")";
    else return print_tuple_utils<i + 1, T>(out << (i ? ", " : "(") << get<i>(tup), tup);
}
template<class ...U>
ostream& operator<<(ostream& out, const tuple<U...>& tup) { return print_tuple_utils<0, tuple<U...>>(out, tup); }
template<class, typename = void> struct has_const_iterator : false_type {};
template<class T> struct has_const_iterator<T, void_t<typename T::const_iterator>> : true_type {};
template<class T>
typename enable_if<has_const_iterator<T>::value && !is_same<T, string>::value, ostream&>::type
operator<<(ostream& out, const T& container) { 
    auto beg = container.begin(), end = container.end();
    out << "(" << container.size() << ") {";
    if (beg != end) out << *(beg++);
    while (beg != end) out << ", " << *(beg++);
    return out << "}";
}
#define ptrtype(x) typename iterator_traits<x>::value_type
template<class u> vector<ptrtype(u)> $v(u a, u b) { return vector<ptrtype(u)>(a, b); }/*}}}*/
// ACTUAL SOLUTION START HERE ////////////////////////////////////////////////////////////////

const int max_col = 400000 + 10;
int n;
int dsu[max_col];
bool has_cycle[max_col];

int find_set(int u) {
    return dsu[u] < 0 ? u : dsu[u] = find_set(dsu[u]);
}

bool join(int u, int v) {
    u = find_set(u);
    v = find_set(v);
    if (u == v) return false;
    if (-dsu[u] < -dsu[v]) swap(u, v);
    dsu[u] += dsu[v];
    if (has_cycle[v]) has_cycle[u] = true;
    dsu[v] = u;
    return true;
}

int main(void) {
#ifdef LOCAL
    freopen("main.inp", "r", stdin);
    freopen("main.out", "w", stdout);
    freopen(".log", "w", stderr);
#endif
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    
    cin >> n;
    memset(dsu, -1, sizeof(dsu));
    memset(has_cycle, 0, sizeof(has_cycle));
    
    rep(i, n) {
        int u, v; cin >> u >> v;
        if (!join(u, v)) {
            has_cycle[find_set(u)] = true;
        }
    }
    
    int ans = 0;
    rep(i, max_col) {
        if (dsu[i] >= 0) continue;
        if (has_cycle[i]) ans += -dsu[i];
        else ans += -dsu[i] - 1;
    }
    cout << ans;
    
    return 0;
}

// vim: foldmethod=marker


#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <cstdio>
#include <cstring>
#define min(a, b) ((a) < (b) ? (a) : (b))

static constexpr int 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 constexpr int mx = 400000;
int p[mx], cnt[mx], siz[mx];

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

int main() {
	int n = getint();
	memset(p, -1, sizeof(p));
	while (n--) {
		int a = get(getint() - 1), b = get(getint() - 1);
		if (a != b) {
			p[b] = a;
			cnt[a] += cnt[b];
		}
		cnt[a]++;
	}
	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]);
		}
	}
	printf("%d", ans);
}
