Problem:
Score : 600 points

Problem Statement

There are N dots in a two-dimensional plane. The coordinates of the i-th dot are (x_i, y_i).

We will repeat the following operation as long as possible:

Choose four integers a, b, c, d (a \neq c, b \neq d) such that there are dots at exactly three of the positions (a, b), (a, d), (c, b) and (c, d), and add a dot at the remaining position.

We can prove that we can only do this operation a finite number of times. Find the maximum number of times we can do the operation.

Constraints

1 \leq N \leq 10^5

1 \leq x_i, y_i \leq 10^5

If i \neq j, x_i \neq x_j or y_i \neq y_j.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
x_1 y_1
:
x_N y_N

Output

Print the maximum number of times we can do the operation.

Sample Input 1

3
1 1
5 1
5 5

Sample Output 1

1

By choosing a = 1, b = 1, c = 5, d = 5, we can add a dot at (1, 5). We cannot do the operation any more, so the maximum number of operations is 1.

Sample Input 2

2
10 10
20 20

Sample Output 2

0

There are only two dots, so we cannot do the operation at all.

Sample Input 3

9
1 1
2 1
3 1
4 1
5 1
1 2
1 3
1 4
1 5

Sample Output 3

16

We can do the operation for all choices of the form a = 1, b = 1, c = i, d = j (2 \leq i,j \leq 5), and no more. Thus, the maximum number of operations is 16.

Solution in C++14 (GCC 5.4.1) (judge verdict: Time Limit Exceeded)

#include <iostream>
#include <utility>
#include <stdint.h>
#include <set>
#include <map>
#include <algorithm>

using namespace std;

int main()
{
  int N;
  cin >> N;

  map<uint32_t, set<uint32_t>> pointsX, pointsY;

  for (int n=0; n<N; ++n) {
    uint32_t x, y;
    cin >> x >> y;
    pointsX[x].insert(y);
    pointsY[y].insert(x);
  }

  uint64_t count = 0;
  while(true) {
    uint64_t old_count = count;

    for (auto itrX1 = pointsX.begin(); itrX1 != pointsX.end(); ++itrX1) {
      for (auto itrX2 = itrX1; itrX2 != pointsX.end(); ++itrX2) {
	if (itrX1->first == itrX2->first)
	  continue;
	set<uint32_t> union_set;
	set_union(itrX1->second.begin(), itrX1->second.end(),
		  itrX2->second.begin(), itrX2->second.end(),
		  inserter(union_set, union_set.end()));
	set<uint32_t> intersection_set;
	set_intersection(itrX1->second.begin(), itrX1->second.end(),
			 itrX2->second.begin(), itrX2->second.end(),
			 inserter(intersection_set, intersection_set.end()));
	if (intersection_set.size() == 0)
	  continue;
	
	if (union_set.size() > itrX1->second.size())
	  count += (union_set.size() - itrX1->second.size());
	if (union_set.size() > itrX2->second.size())
	  count += (union_set.size() - itrX2->second.size());

	itrX1->second = union_set;
	itrX2->second = union_set;
	for (uint32_t y : union_set) {
	  pointsY[y].insert(itrX1->first);
	  pointsY[y].insert(itrX2->first);
	}
      }
    }

    for (auto itrY1 = pointsY.begin(); itrY1 != pointsY.end(); ++itrY1) {
      for (auto itrY2 = itrY1; itrY2 != pointsY.end(); ++itrY2) {
	if (itrY1->first == itrY2->first)
	  continue;

	set<uint32_t> union_set;
	set_union(itrY1->second.begin(), itrY1->second.end(),
		  itrY2->second.begin(), itrY2->second.end(),
		  inserter(union_set, union_set.end()));
	set<uint32_t> intersection_set;
	set_intersection(itrY1->second.begin(), itrY1->second.end(),
			 itrY2->second.begin(), itrY2->second.end(),
			 inserter(intersection_set, intersection_set.end()));
	if (intersection_set.size() == 0)
	  continue;

	if (union_set.size() > itrY1->second.size())
	  count += (union_set.size() - itrY1->second.size());
	if (union_set.size() > itrY2->second.size())
	  count += (union_set.size() - itrY2->second.size());
	itrY1->second = union_set;
	itrY2->second = union_set;
	for (uint32_t x : union_set) {
	  pointsX[x].insert(itrY1->first);
	  pointsX[x].insert(itrY2->first);
	}
      }
    }

    if (old_count == count)
      break;
  }

  cout << count << endl;

  return 0;
}