#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <numeric>
#include <cmath>
#include <unordered_map>

using namespace std;
using ll = long long;

void _cin(){} template <class Head, class... Tail> void _cin(Head&& head, Tail&&... tail){ cin >> head; _cin(forward<Tail>(tail)...); }
void _cout(){ cout << "\n"; } template <class Head, class... Tail> void _cout(Head&& head, Tail&&... tail){ cout << head; _cout(forward<Tail>(tail)...); }
ll gcd(ll a, ll b){ return (b == 0) ? a : gcd(b, a % b); }

#define Sq(x) (x)*(x)
#define For(i, n) for(int i = 0; i < (n); i ++)
#define Rep(n) For(_, n)
#define Range(c) c.begin(), c.end()
#define RevRange(c) c.rbegin(), c.rend()
#define Contains(c, x) (find(Range(c), x) != c.end())
#define Search(rb, re, x) distance(rb, find(rb, re, x))
#define Sort(a) sort(Range(a))
#define DeSort(a) sort(RevRange(a))
#define Reverse(c) reverse(Range(c))
#define Unique(a) a.erase(unique(Range(a)), a.end())
#define Cusum(T, xs, sxs) vector<T> sxs(xs.size()+1); For(i, (int)xs.size()) sxs[i+1] = sxs[i] + xs[i]
#define Cin(T, ...) T __VA_ARGS__; _cin(__VA_ARGS__)
#define Cins(T, n, xs) vector<T> xs(n); For(i, n) cin >> xs[i]
#define Cins2(T, n, xs, ys) vector<T> xs(n), ys(n); For(i, n) cin >> xs[i] >> ys[i]
#define Cins3(T, n, xs, ys, zs) vector<T> xs(n), ys(n), zs(n); For(i, n) cin >> xs[i] >> ys[i] >> zs[i]
#define Cinss(T, n, m, xs) Vec2(T, n, m, xs); For(i, n) For(j, m) cin >> xs[i][j]
#define Cinm(T, n, map) unordered_map<T, int> map; Rep(n){ Cin(T, x); map[x] ++; }
#define Cout(...) _cout(__VA_ARGS__)
#define Couts(xs) { for(const auto &e : xs) cout << e << " "; cout << "\n"; }
#define Coutyn(cond) Cout((cond) ? "yes" : "no")
#define CoutYn(cond) Cout((cond) ? "Yes" : "No")
#define CoutYN(cond) Cout((cond) ? "YES" : "NO")
#define vc vector
#define Mini(a, x) a = min(a, x)
#define Maxi(a, x) a = max(a, x)

// constexpr int MOD = 1e9+7;

class UFT{
public:
    vector<int> par;
    vector<int> siz;
    vector<int> mar;


    UFT(int n) :
        par(vector<int>(n)),
        siz(vector<int>(n, 1)),
        mar(vector<int>(n, 0)){ For(i, n) par[i] = i; }

    bool same(int x, int y){ return find(x) == find(y); }
    int find(int x){ return (par[x] == x) ? x : (par[x] = find(par[x])); }
    void unite(int x, int y){
        if(!same(x = find(x), y = find(y))){
            par[x] = y;
            siz[y] += siz[x];
            mar[y] += mar[x];
        }
    }
    int size(int x){ return siz[find(x)]; }
    void add(int x){ mar[find(x)] ++; }
    int count(int x){ return mar[find(x)]; }
    void print() const{ Couts(par); }
};

int main(void){
    Cin(int, n);
    vc<pair<int, int>> p(n);
    #define x first
    #define y second
    vc<int> px(n), py(n);
    unordered_map<int, int> mx, my;
    For(i, n){
        cin >> p[i].x >> p[i].y;
        px[i] = p[i].x;
        py[i] = p[i].y;
    }
    Sort(px); Unique(px);
    Sort(py); Unique(py);
    int sx = px.size();
    int sy = py.size();
    For(i, sx) mx[px[i]] = i;
    For(i, sy) my[py[i]] = i;
    For(i, n){
        p[i].x = mx[p[i].x];
        p[i].y = my[p[i].y];
    }
    Sort(p);
    
    //For(i, n) Cout("> ", p[i].x, " ", p[i].y);
    UFT uft(sy);
    int j = 0;
    For(i, sx){
        int y0 = p[j].y;
        while(j < n && p[j].x == i){
            uft.unite(y0, p[j].y);
            j ++;
        }
        uft.add(y0);
        //Cout("[", uft.mar[y0], "]");
    }

    ll ans = 0;
    vc<bool> alr(sy, false);

    For(i, sy){
        int x = uft.find(i);
        if(!alr[x]){
            //Cout(i, " ", uft.count(i), " ", uft.size(i));
            alr[x] = true;
            ans += (ll)uft.count(i) * uft.size(i);
        }
    }
    Cout(ans - n);
}


Measured memory_bytes: 6540