#include <bits/stdc++.h>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/rope>
using namespace std;
//usin	g namespace __gnu_pbds;
//using namespace __gnu_cxx;
//template<class T> using Tree = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>;

using namespace std;
#define go ios::sync_with_stdio(0);cin.tie(nullptr);cout.tie(nullptr);
#define ll long long
const int mxn = 2e5 + 5 , mod = 1e9 + 7 , MOD = 1e9 + 7 , mod2 = 998244353;
int n ;
vector<int>vi[mxn * 2];
int siz ;
bool ok ;
bool exist[mxn * 2] , vis[mxn * 2];
void dfs(int node, int par = -1){
	vis[node] = true;
	siz++;
	for(auto it : vi[node]){
		if(it == par)
			continue;
		if(vis[it])ok = true;
		if(!vis[it])
		dfs(it , node);
	}
}
void bingo(){
	cin>>n;
	map<int,int>mp;
	int mx = 0;
	for(int i =0 ;i < n ; i++){
		int u , v;
		cin>>u>>v;
		vi[u].push_back(v);
		vi[v].push_back(u);
		mx = max({mx , u , v});
		exist[u] = exist[v] = true;
	}
	int out = 0;
	for(int i = 1 ; i <= mx  ; i++){
		if(exist[i] && !vis[i] ){
			ok = false;
			siz = false ;
			dfs(i);
			if(ok)out += siz;
			else out += siz - 1;
		}
	}
	cout<<out;
}
int main() {
	go
#ifdef LOCAL
	freopen("input.in", "rt", stdin);
//	freopen("output.in", "wt", stdout);
#endif
	int t = 1;
	//cin>>t;
	while(t--){
		bingo();
	}
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (n); ++i)
using edge = pair<int, int>;

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    const int MX = 400000;

    int n;
    cin >> n;

    vector<vector<edge>>  g(MX, vector<edge>());
    unordered_set<int> color;
    rep(i, n) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        g[a].emplace_back(b, i);
        g[b].emplace_back(a, i);
        color.insert(a);
        color.insert(b);
    }

    vector<bool> vis(MX, false);

    auto is_tree = [&](auto self, int v, int i = -1) -> bool {
        // @return 
        // true=木
        // false=サイクル
        bool ret = true;
        vis[v] = true;
        for (auto [u, j] : g[v]) {
            if (j == i) continue; // 訪問に用いた辺を逆にたどっている
            if (vis[u]) {
                ret = false;
                continue;
            }
            if (!self(self, u, j)) ret = false;
        }
        return ret;
    };

    int ans = (int)color.size();
    for (auto v : color) {
        if (vis[v]) continue;
        if (is_tree(is_tree, v)) ans--;
    }

    cout << ans << "\n"s;

    return 0;
}
