#include <stdio.h>
#include <cstdio>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
#include <cstring>
#include <algorithm>

class pt{
public:
  long long int x, y, group, index;
  //rank;
};

bool compx(const class pt pt1, const class pt pt2){
  return pt1.x < pt2.x;
}

bool compy(const class pt pt1, const class pt pt2){
  return pt1.y < pt2.y;
}
bool compgrp(const class pt pt1, const class pt pt2){
  return pt1.group < pt2.group;
}
bool compindex(const class pt pt1, const class pt pt2){
  return pt1.index < pt2.index;
}

/*long long int find_group(std::vector<class pt> &points, long long int i1){
  
  if(points[i1].group == points[i1].index)return i1;
  long long int ans;
  ans = find_group(points, points[i1].group);
  points[i1].group = ans;
  return ans;
}*/
  
long long int find_root(std::vector<long long int> &root, long long int i1){
  
  if(root[i1] == i1)return i1;
  long long int ans;
  ans = find_root(root, root[i1]);
  root[i1] = ans;
  return ans;
}

/*int unite(std::vector<class pt> &points, long long int i1, long long int i2){
  i1 = find_group(points, i1);
  i2 = find_group(points, i2);
  
  if(points[i1].rank < points[i2].rank){
    points[i1].group = points[i1].group;
  }
  else if(points[i1].rank > points[i2].rank){
    points[i2].group = i1;
  }
  else{
    points[i1].group = i2;
    points[i2].rank++;
  }
  return 0;
}*/

int unite(std::vector<long long int> &root, std::vector<long long int> &rank, long long int i1, long long int i2){
  i1 = find_root(root, i1);
  i2 = find_root(root, i2);
  
  if(rank[i1] < rank[i2]){
    root[i1] = i2;
  }
  else if(rank[i1] > rank[i2]){
    root[i2] = i1;
  }
  else{
    root[i1] = i2;
    rank[i2]++;
  }
  return 0;
}

int main(){
  
  // read problem
  long long int N, tmp1, tmp2;
  scanf("%lld", &N);
  std::vector<class pt> points(N);
  std::vector<long long int> root(N), rank(N);
  for(long long int i = 0; i < N; i++){
    scanf("%lld%lld", &tmp1, &tmp2);
    points[i].x = tmp1;
    points[i].y = tmp2;
    points[i].group = i;
    root[i] = i;
    points[i].index = i;
    //points[i].rank = 0;
    rank[i] = 0;
  }
  
  /*std::cerr << "original points" << std::endl;
  for(long long int i = 0; i < N; i++){
    std::cerr << points[i].x << " " << points[i].y << " " << points[i].group << std::endl;
  }*/
  
  // do union find
  std::sort(points.begin(), points.end(), compx);
  
  /*std::cerr << "sorted in terms of x coordinate" << std::endl;
  for(long long int i = 0; i < N; i++){
    std::cerr << points[i].x << " " << points[i].y << " " << points[i].group << std::endl;
  }*/
  
  long long int group_tmp = 0;
  for(long long int i = 1; i < N; i++){
    if(points[i].x == points[i-1].x){
      unite(root, rank, points[group_tmp].index, points[i].index);
      //unite(points, group_tmp, i);
    }
    else{
      group_tmp = i;
    }
  }
  
  std::sort(points.begin(), points.end(), compy);
  
  /*std::cerr << "sorted in terms of y coordinate" << std::endl;
  for(long long int i = 0; i < N; i++){
    std::cerr << points[i].x << " " << points[i].y << " " << points[i].group << std::endl;
  }*/
  
  group_tmp = 0;
  for(long long int i = 1; i < N; i++){
    if(points[i].y == points[i-1].y){
      unite(root, rank, points[group_tmp].index, points[i].index);
      //unite(points, group_tmp, i);
    }
    else{
      group_tmp = i;
    }
  }
  
  // update group
  for(long long int i = 0; i < N; i++){
    points[i].group = find_root(root, points[i].index);
  }
  
  std::sort(points.begin(), points.end(), compgrp);
  
  /*std::cerr << "sorted in terms of groups:" << std::endl;
  for(long long int i = 0; i < N; i++){
    std::cerr << points[i].x << " " << points[i].y << " " << points[i].group << std::endl;
  }*/
  
  std::vector<long long int> xcount(1e5+1), ycount(1e5+1);
  long long int ans = 0;
  long long int grp_xcnt=0, grp_ycnt=0;
  tmp1 = 0;
  group_tmp = -1;
  for(long long int i = 0; i < N; i++){
    // new group is found
    if(points[i].group != group_tmp){
      //std::cerr << "new group found: i = " << i << std::endl;
      // update answer
      ans += grp_xcnt*grp_ycnt - (i-tmp1);
      //std::cerr << grp_xcnt << " " << grp_ycnt << " " << i << " " << tmp1 << std::endl;
      //std::cerr << "ans = " << ans << std::endl;
      //reset state
      for(long long int j = tmp1; j < i; j++){
        grp_xcnt = 0;
        grp_ycnt = 0;
        xcount[points[j].x] = 0;
        ycount[points[j].y] = 0;
      }
      // update group property
      tmp1 = i;
      group_tmp = points[i].group;
    }
    
    // update state
    if(xcount[points[i].x] == 0){
      xcount[points[i].x] = 1;
      grp_xcnt++;
    }
    if(ycount[points[i].y] == 0){
      ycount[points[i].y] = 1;
      grp_ycnt++;
    }
  }
  
  // last group
  //std::cerr << grp_xcnt << " " << grp_ycnt << " " << N << " " << tmp1 << std::endl;
  ans += grp_xcnt*grp_ycnt - (N-tmp1);
  
  std::cerr << "Answer:" << std::endl;
  std::cout << ans << std::endl;
  
  return 0;
}


Measured memory_bytes: 6528