/**
 *  created: 09/01/2021, 14:06:07
**/

#include <bits/stdc++.h>

using namespace std;

const int max_n = 600666, inf = 1000111222;

namespace max_flow {

const int max_v = max_n, inf = 1000111222;

struct edge {
    int to, residual_capacity;

    edge(int to, int residual_capacity): to(to), residual_capacity(residual_capacity) {
    }
};

vector<edge> edges;
vector<int> g[max_v];

void add_edge(int u, int v, int capacity) {
    g[u].push_back(edges.size());
    edges.push_back({v, capacity});
    g[v].push_back(edges.size());
    edges.push_back({u, 0});
}

int h[max_v], num[max_v];

bool bfs(int s, int t) {
    memset(h, -1, sizeof(h[0]) * (t + 1));
    h[s] = 0;
    queue<int> q;
    q.push(s);
    while (!q.empty()) {
        int v = q.front();
        q.pop();
        if (v == t) {
            return true;
        }
        for (int id : g[v]) {
            if (edges[id].residual_capacity && h[edges[id].to] == -1) {
                h[edges[id].to] = h[v] + 1;
                q.push(edges[id].to);
            }
        }
    }
    return h[t] != -1;
}

int dfs(int v, int t, int f) {
    if (v == t) {
        return f;
    }
    for (int &i = num[v]; i < g[v].size(); ++i) {
        const int id = g[v][i];
        if (edges[id].residual_capacity && h[v] + 1 == h[edges[id].to]) {
            int res = dfs(edges[id].to, t, min(f, edges[id].residual_capacity));
            if (res) {
                edges[id].residual_capacity -= res;
                edges[id ^ 1].residual_capacity += res;
                return res;
            }
        }
    }
    return 0;
}

int dinic(int s, int t) {
    int res = 0;
    while (bfs(s, t)) {
        memset(num, 0, sizeof(num[0]) * (t + 1));
        while (int f = dfs(s, t, inf)) {
            res += f;
        }
    }
    return res;
}

void clr(int t) {
    edges.clear();
    for (int i = 0; i <= t; ++i) {
        g[i].clear();
    }
}

}

int n, a[max_n], b[max_n];
vector<int> v;

int compress(int x) {
    return lower_bound(v.begin(), v.end(), x) - v.begin();
}

int main() {
    //freopen("in/1_025.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d%d", &a[i], &b[i]);
        v.push_back(a[i]);
        v.push_back(b[i]);
    }
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    int s = n + v.size(), t = n + v.size() + 1;
    for (int i = 0; i < n; ++i) {
        a[i] = compress(a[i]);
        b[i] = compress(b[i]);
        max_flow::add_edge(s, i, 1);
        max_flow::add_edge(i, n + a[i], 1);
        if (i != a[i]) {
            max_flow::add_edge(i, n + b[i], 1);
        }
    }
    for (int i = 0; i < v.size(); ++i) {
        max_flow::add_edge(n + i, t, 1);
    }
    int ans = max_flow::dinic(s, t);
    printf("%d\n", ans);
    return 0;
}

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

typedef pair<int,int> pii;
typedef pair<string,int> psi;
typedef pair<int,string> pis;
typedef array<int,2> aii;
typedef array<int,3> aiii;
typedef array<int,4> aiiii;
typedef unsigned long long ull;
typedef long long int ll;
typedef array<ll,2> all;
typedef array<ll,3> alll;

#define pb push_back
#define ff first
#define ss second
#define MAX 200005
#define MOD 1000000007
#define INF 1e9+100
vector<int>adj[2*MAX];
int xMove[] = { 0,1,0,-1,1,1,-1,-1, 2, 2, -2, -2, 1, 1, -1, -1 };
int yMove[] = { 1,0,-1,0,1,-1,1,-1, 1, -1, 1, -1, 2, -2, 2, -2 };

int p[2*MAX],sz[2*MAX][2];
void init()
{
    for(int i=1;i<=400000;i++)
        p[i]=i,sz[i][0]=1;
}

int find_parent(int u)
{
    return p[u]=p[u]==u?u:find_parent(p[u]);
}

void union_sets(int u, int v)
{
    int pu=find_parent(u);
    int pv=find_parent(v);

    if(pu!=pv)
    {
        if(sz[pu][0]<sz[pv][0])
            swap(pu,pv);

        p[pv]=pu;
        sz[pu][0]+=sz[pv][0];
        sz[pu][1]+=1+sz[pv][1];
    }
    else sz[pu][1]++;
}
int main()
{
//    freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    cin.tie(0),cout.tie(0);
    ios_base::sync_with_stdio(0);
    cout.setf(ios::fixed);
    cout.precision(10);
    int TC=1;
    int n,m,q;
    //cin>>TC;
    for(int t1=1; t1<=TC; t1++)
    {
        cin>>n;
        init();
        for(int i=0; i<n; i++)
        {
            int a,b;
            cin>>a>>b;

            union_sets(a,b);
        }

        bool processed[2*MAX]={};
        int ans=0;
        for(int i=1;i<=400000;i++)
        {
            int p=find_parent(i);
            if(!processed[p])
            {
                processed[p]=1;
                ans+=min(sz[p][0],sz[p][1]);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
