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 (GCC 9.2.1) (judge verdict: Runtime Error)

#include <stdio.h>
#include <stdlib.h>

typedef struct List {
	struct List *next;
	int v;
} list;

typedef struct {
	int *par, *size, *height;
} UF_forest;

void UF_initialize(UF_forest *F, int n)
{
	int i;
	F->par = (int*)malloc(sizeof(int) * (n + 1));
	F->size = (int*)malloc(sizeof(int) * (n + 1));
	F->height = (int*)malloc(sizeof(int) * (n + 1));
	for (i = 1; i <= n; i++) {
		F->par[i] = i;
		F->size[i] = 1;
		F->height[i] = 1;
	}
}

void UF_merge(UF_forest *F, int u, int v)
{
	for (; F->par[u] != u; u = F->par[u]);
	for (; F->par[v] != v; v = F->par[v]);
	if (u == v) return;
	else if (F->height[u] > F->height[v]) {
		F->par[v] = u;
		F->size[u] += F->size[v];
	} else {
		F->par[u] = v;
		F->size[v] += F->size[u];
		if (F->height[u] == F->height[v]) F->height[v]++;
	}
}

int UF_root(UF_forest *F, int v)
{
	for (; F->par[v] != v; v = F->par[v]);
	return v;
}

int UF_size(UF_forest *F, int v)
{
	for (; F->par[v] != v; v = F->par[v]);
	return F->size[v];
}

int main()
{
	int i, N, x[100001], y[100001];
	scanf("%d", &N);
	for (i = 1; i <= N; i++) scanf("%d %d", &(x[i]), &(y[i]));

	list *p, *q, *X[100001] = {}, *Y[100001] = {}, d[200003];
	for (i = 1; i <= N; i++) {
		d[i*2].v = y[i];
		d[i*2+1].v = x[i];
		d[i*2].next = X[x[i]];
		d[i*2+1].next = Y[y[i]];
		X[x[i]] = &(d[i*2]);
		Y[y[i]] = &(d[i*2+1]);
	}

	UF_forest F[2];
	UF_initialize(&(F[0]), 100000);
	UF_initialize(&(F[1]), 100000);
	for (i = 1; i <= 100000; i++) {
		if (X[i] == NULL || X[i]->next == NULL) continue;
		for (p = X[i]->next; p != NULL; p = p->next) if (Y[p->v] != NULL && Y[p->v]->next != NULL) break;
		if (p == NULL) continue;
		for (p = X[i]->next; p != NULL; p = p->next) {
			UF_merge(&(F[1]), X[i]->v, p->v);
			for (q = Y[p->v]->next; q != NULL; q = q->next) UF_merge(&(F[0]), i, q->v);
		}
	}
	for (i = 1; i <= 100000; i++) {
		if (Y[i] == NULL || Y[i]->next == NULL) continue;
		for (q = Y[i]->next; q != NULL; q = q->next) if (X[q->v] != NULL && X[q->v]->next != NULL) break;
		if (q == NULL) continue;
		for (q = Y[i]->next; q != NULL; q = q->next) {
			UF_merge(&(F[0]), Y[i]->v, q->v);
			for (p = Y[q->v]->next; p != NULL; p = p->next) UF_merge(&(F[1]), i, p->v);
		}
	}
	return 0;
	
	int r, flag[100001] = {};
	long long ans = 0;
	for (i = 1; i <= N; i++) {
		r = UF_root(&(F[0]), x[i]);
		if (flag[r] == 1) continue;
		else flag[r] = 1;
		ans += (long long)UF_size(&(F[0]), r) * UF_size(&(F[1]), y[i]);
	}
	printf("%lld\n", ans - N);
	fflush(stdout);
	return 0;
}