#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using vl = vector<ll>;
using vvl = vector<vl>;
using pl = pair<ll, ll>;
const ll INF = ll(1e18);
const ll mod = ll(1e9 + 7);
const double pi = acos(-1);
#define rep0(i,n) for(ll (i) = 0; (i) < (n); ++(i))
#define rrep0(i,n) for(ll (i) = (n) - 1; (i) >= 0; --(i))
#define rep1(i,n) for(ll (i) = 1; (i) <= (n); ++(i))
#define rrep1(i,n) for(ll (i) = (n); (i) >= 1; --(i))
#define nfor(i,a,b) for(ll (i) = (a); (i) < (b); ++(i))
#define rnfor(i,a,b) for(ll (i) = (b) - 1; (i) >= (a); --(i))
#define pf(x) cout << (x) << endl
#define all(x) (x).begin(),(x).end()
#define yes pf("Yes")
#define no pf("No")
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

int multipf(vector<string>& s){
    cout << s[0];
    rep1(i, s.size() - 1)cout << " " << s[i];
    cout << endl;
    return 0;
}

int multipf(vector<ll>& n){
    cout << n[0];
    rep1(i, n.size() - 1)cout << " " << n[i];
    cout << endl;
    return 0;
}

ll gcd(ll a,ll b){
    if(a < b)swap(a, b);
    if(b == 0) return a;
    return gcd(b,a%b);
}
 
ll lcm(ll a,ll b){
    ll g = gcd(a,b);
    return a / g * b;
}

ll factorial(ll n){
    ll ans = 1;
    rep1(i, n){
        ans *= i;
        ans %= mod;
    }
    return ans;
}

ll power(ll a, ll b){
    ll ans = 1;
    while(b) {
        if(b & 1LL) ans = ans * a % mod;
        ans %= mod;
        a = a * a;
        a %= mod;
        b >>= 1;
    }
    return ans % mod;
}

struct UnionFind {
    vector<ll> par;
    vector<ll> rank;
    vector<ll> Size;
    UnionFind(ll n) {
        init(n);
    }
 
    void init(ll n) {
        par.resize(n + 1); rank.resize(n + 1); Size.resize(n + 1);
        rep0(i, n + 1){
            par[i] = i;
            rank[i] = 0;
            Size[i] = 1;
        }
    }
 
    ll root(ll x) {
        if (par[x] == x) return x;
        else return par[x] = root(par[x]);
    }
 
    bool same(ll x, ll y) {
        return root(x) == root(y);
    }
 
    bool merge(ll x, ll y) {
        x = root(x); y = root(y);
        if (x == y) return false;
        if (rank[x] < rank[y]) swap(x, y);
        if (rank[x] == rank[y]) ++rank[x];
        par[y] = x;
        Size[x] += Size[y];
        return true;
    }
 
    ll size(ll x){
        return Size[root(x)];
    }
};

//modの値の確認をすること
int main(){
    ll n;
    cin >> n;
    vl cnt(400001,0);
    UnionFind u(400001);
    rep0(i, n){
        ll a,b;
        cin >> a >> b;
        cnt[a]++;
        cnt[b]++;
        u.merge(a, b);
    }
    rep0(i, 400001)if(u.root(i) != i)cnt[u.root(i)] += cnt[i];
    ll ans = 0;
    vector<bool> f(400001,false);
    rep0(i, 400001){
        if(u.root(i) != i)continue;
        if(u.size(i) >= cnt[i] / 2)ans += cnt[i] / 2;
        else ans += u.size(i);
    }
    pf(ans);
    return 0;
}

#include "bits/stdc++.h"
using namespace std;
#define int long long
vector<vector<int>> adj;
vector<int> vis;
vector<int> sel;
int cnt, nn, edges;
void dfs(int root, int parent) {
	vis[root] = 1;
	cnt++;
	edges += sel[root];
	for (auto i : adj[root]) {
		if (!vis[i]) {
			//cout << i << " ";
			dfs(i, parent);
		}
	}
}

int32_t main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	set<int> s;
	int n;
	cin >> n;
	vector<pair<int, int>> v;
	int t = 1;
	map<int, int> m;
	for (int i = 0; i < n; i++) {
		int a, b;
		cin >> a >> b;
		if (a > b)swap(a, b);
		v.push_back(make_pair(a, b));
		if (m[a] == 0) {
			m[a] = t;
			t++;
		}
		if (m[b] == 0) {
			m[b] = t;
			t++;
		}
		s.insert(a);
		s.insert(b);
	}

	nn = s.size();
	adj = vector<vector<int>>(nn);
	vis = vector<int> (nn, 0);
	sel = vector<int> (nn, 0);
	for (int i = 0; i < n; i++) {
		int a = v[i].first, b = v[i].second;
		adj[m[a] - 1].push_back(m[b] - 1);
		adj[m[b] - 1].push_back(m[a] - 1);
		sel[m[a] - 1]++;
	}
	int best = 0;
	for (int i = 0; i < nn; i++) {
		if (!vis[i]) {
			//cout << i << "\n";
			edges = 0;
			cnt = 0;
			dfs(i, i);
			//cout << edges << "\n";
			best += max(min(cnt, edges), 1ll);
		}
	}
	cout << best << "\n";
	return 0;
}