#pragma GCC target ("avx2")
#pragma GCC optimize ("O3")
#pragma GCC optimize ("unroll-loops")
#include <bits/stdc++.h>

using namespace std;
typedef long long int ll;
typedef long double ld;

#define S 600020

struct dinic {
	struct edge {int b, cap, flow, flip;};
	vector<edge> g[S+2];
	int ans=0, d[S+2], ptr[S+2];

	void add_edge (int a, int b, int cap) {
		g[a].push_back({b, cap, 0, g[b].size()});
		g[b].push_back({a, 0, 0, g[a].size()-1});
	}
	
	int dfs (int u, int flow=INT_MAX) {
		if (u==S+1 || !flow) return flow;
		while (++ptr[u] < g[u].size()) {
			edge &e = g[u][ptr[u]];
			if (d[e.b] != d[u]+1) continue;
			if (int pushed = dfs(e.b, min(flow, e.cap-e.flow))) {
				e.flow += pushed;
				g[e.b][e.flip].flow -= pushed;
				return pushed;
			}
		}
		return 0;
	}

	void calc() {
		do {
			vector<int> q {S};
			memset(d, 0, sizeof d);
			int i = -(d[S] = 1);
			while (++i<q.size() && !d[S+1])
				for (auto e: g[q[i]])
					if (!d[e.b] && e.flow<e.cap) {
						q.push_back(e.b);
						d[e.b] = d[q[i]]+1;
					}

			memset(ptr, -1, sizeof ptr);
			while(int pushed=dfs(S)) ans+=pushed;
		} while (d[S+1]);
	}
};


dinic flow;
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n;
	cin>>n;
	set<int> colors;
	for (int i=0; i<n; ++i) {
		int a, b;
		cin>>a>>b;
		flow.add_edge(S, i, 1);
		flow.add_edge(i, a+n, 1);
		flow.add_edge(i, b+n, 1);
		colors.insert(a);
		colors.insert(b);
	}
	for (auto c:colors) {
		flow.add_edge(c+n, S+1, 1);
	}
	flow.calc();
	cout<<flow.ans<<endl;
}


#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl '\n'
#define pb push_back
#define pob pop_back
#define pii pair<int,int>
// int mod = 3;
#define mod 1000000007
// #define mod 1000000009
// #define mod 163577857
// #define mod 998244353
#define rep(i,n) for (int i = 0; i < n; i++)
#define repp(i,a,b) for(int i = a ; i<b ; i++)
#define reppr(i,a,b) for(int i = a-1 ; i>=b ; i--)
#define repr(i,n) for (int i = n - 1; i >= 0; i--)
#define ff first
#define ss second
#define inf 9223372036854775807
#define infn -9223372036854775807
#define pi 3.14159265358979323846
#define eps 0.0000000001
#define setprec(x) cout << fixed << setprecision(x);
#define REVERSE(a) reverse(all(a));
#define SORT(a) sort(all(a));
#define all(n) n.begin(),n.end()
#define setbits(x) __builtin_popcountll(x)
 
//GCD and LCM
    int gcd (int a, int b) { return b ? gcd (b, a % b) : a; }
    int lcm (int a, int b) { return a / gcd(a, b) * b; }

//Modular Exponentiation
    int powmod(int x,int y)
    {
        if (y == 0) return 1;
        int p = powmod(x, y/2) % mod;
        p = (p * p) % mod;
        return (y%2 == 0)? p : (x * p) % mod;
    }
 
//Modular Inverse
    int inverse(int a)
    {
       return powmod(a,mod-2);
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////NO TEXT ABOVE IT//////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool codejam = 0, testcases = 0;

int parent[400001];
int rank[400001];
int find_set(int v) {
    if (v == parent[v])
        return v;
    return find_set(parent[v]);
}

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


void solve()
{
    int n , a , b;
    cin >> n;    
    map<int,vector<int>> m;
    repp(i,1,400001)
        parent[i] = i;
    rep(i,n)
    {
        cin >> a >> b;
        if(a>b) swap(a,b);
        m[a].pb(b);
    }
    set<int> ans;
    for(auto i : m)
    {
        for(auto j : i.ss)
        {
            if(ans.find(find_set(j))==ans.end())
                ans.insert(find_set(j)) , union_sets(i.ff,j);
            else
                ans.insert(find_set(i.ff));
        }
    }
    cout << ans.size() << endl;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////NO TEXT BELOW IT//////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
signed main()
{
    ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
    int t = 1;
    if(testcases) 
        cin >> t;
    rep(i,t)
    {
        if(codejam)
            cout << "Case #" << i+ 1<< ": ";
        solve();
    }
}   