import sys

sys.setrecursionlimit(10**7)

INF = 10 ** 18

MOD = 10 ** 9 + 7

def YesNo(x): return 'Yes' if x else 'No'

def LI(): return [int(x) for x in sys.stdin.readline().split()]

def LI_(): return [int(x) - 1 for x in sys.stdin.readline().split()]

def LF(): return [float(x) for x in sys.stdin.readline().split()]

def LS(): return sys.stdin.readline().split()

def II(): return int(sys.stdin.readline())

def SI(): return eval(input())

from collections import defaultdict



def main():

    N = II()

    edges = defaultdict(list)

    for _ in range(N):

        x, y = LI()

        edges[x].append(-y)

        edges[-y].append(x)

    visited = defaultdict(int)

    if max(len(li) for li in list(edges.values())) == 2 and N >= 10 ** 4:

        m, p = 0, 0

        for k in list(edges.keys()):

            if k < 0:

                m += 1

            else:

                p += 1

        return m * p - N

    def solve(v):

        visited[v] = 1

        ret = [v]

        for u in edges[v]:

            if not visited[u]:

                ret += solve(u)

        return ret

    ans = -N

    for node in edges:

        if not visited[node]:

            li = solve(node)

            m, p = 0, 0

            for z in li:

                if z < 0:

                    m += 1

                else:

                    p += 1

            ans += m * p

    return ans



print((main()))
import sys

sys.setrecursionlimit(10**7)

INF = 10 ** 18

MOD = 10 ** 9 + 7

def YesNo(x): return 'Yes' if x else 'No'

def LI(): return [int(x) for x in sys.stdin.readline().split()]

def LI_(): return [int(x) - 1 for x in sys.stdin.readline().split()]

def LF(): return [float(x) for x in sys.stdin.readline().split()]

def LS(): return sys.stdin.readline().split()

def II(): return int(sys.stdin.readline())

def SI(): return eval(input())

from collections import defaultdict



def main():

    N = II()

    xy = []

    for _ in range(N):

        xy.append(LI())

    xy2g = defaultdict(int)

    g2xy = defaultdict(set)

    for x, y in xy:

        y = -y

        gx = xy2g[x]

        gy = xy2g[y]

        if gx == gy != 0:

            continue

        elif gx != 0 != gy:  # merge

            if len(g2xy[gx]) < len(g2xy[gy]):

                gx, gy = gy, gx

            for xy in g2xy[gy]:

                xy2g[xy] = gx

            g2xy[gx] |= g2xy[gy]

            g2xy[gy].clear()

        else:

            g = gx or gy or x

            xy2g[x] = xy2g[y] = g

            g2xy[g] |= {x, y}

    ans = -N

    for xys in list(g2xy.values()):

        nx = sum(xy > 0 for xy in xys)

        ny = len(xys) - nx

        ans += nx * ny

    return ans



print((main()))
import sys

sys.setrecursionlimit(10**7)
INF = 10**18
MOD = 10**9 + 7


def YesNo(x):
    return "Yes" if x else "No"


def LI():
    return [int(x) for x in sys.stdin.readline().split()]


def LI_():
    return [int(x) - 1 for x in sys.stdin.readline().split()]


def LF():
    return [float(x) for x in sys.stdin.readline().split()]


def LS():
    return sys.stdin.readline().split()


def II():
    return int(sys.stdin.readline())


def SI():
    return eval(input())


from collections import defaultdict


def main():
    N = II()
    edges = defaultdict(list)
    for _ in range(N):
        x, y = LI()
        edges[x].append(-y)
        edges[-y].append(x)
    visited = defaultdict(int)
    if max(len(li) for li in list(edges.values())) == 2 and N >= 10**4:
        m, p = 0, 0
        for k in list(edges.keys()):
            if k < 0:
                m += 1
            else:
                p += 1
        return m * p - N

    def solve(v):
        visited[v] = 1
        ret = [v]
        for u in edges[v]:
            if not visited[u]:
                ret += solve(u)
        return ret

    ans = -N
    for node in edges:
        if not visited[node]:
            li = solve(node)
            m, p = 0, 0
            for z in li:
                if z < 0:
                    m += 1
                else:
                    p += 1
            ans += m * p
    return ans


print((main()))

import sys

sys.setrecursionlimit(10**7)
INF = 10**18
MOD = 10**9 + 7


def YesNo(x):
    return "Yes" if x else "No"


def LI():
    return [int(x) for x in sys.stdin.readline().split()]


def LI_():
    return [int(x) - 1 for x in sys.stdin.readline().split()]


def LF():
    return [float(x) for x in sys.stdin.readline().split()]


def LS():
    return sys.stdin.readline().split()


def II():
    return int(sys.stdin.readline())


def SI():
    return eval(input())


from collections import defaultdict


def main():
    N = II()
    xy = []
    for _ in range(N):
        xy.append(LI())
    xy2g = defaultdict(int)
    g2xy = defaultdict(set)
    for x, y in xy:
        y = -y
        gx = xy2g[x]
        gy = xy2g[y]
        if gx == gy != 0:
            continue
        elif gx != 0 != gy:  # merge
            if len(g2xy[gx]) < len(g2xy[gy]):
                gx, gy = gy, gx
            for xy in g2xy[gy]:
                xy2g[xy] = gx
            g2xy[gx] |= g2xy[gy]
            g2xy[gy].clear()
        else:
            g = gx or gy or x
            xy2g[x] = xy2g[y] = g
            g2xy[g] |= {x, y}
    ans = -N
    for xys in list(g2xy.values()):
        nx = sum(xy > 0 for xy in xys)
        ny = len(xys) - nx
        ans += nx * ny
    return ans


print((main()))

-    edges = defaultdict(list) +    xy = [] -        x, y = LI() -        edges[x].append(-y) -        edges[-y].append(x) -    visited = defaultdict(int) -    if max(len(li) for li in list(edges.values())) == 2 and N >= 10**4: -        m, p = 0, 0 -        for k in list(edges.keys()): -            if k < 0: -                m += 1 -            else: -                p += 1 -        return m * p - N - -    def solve(v): -        visited[v] = 1 -        ret = [v] -        for u in edges[v]: -            if not visited[u]: -                ret += solve(u) -        return ret - +        xy.append(LI()) +    xy2g = defaultdict(int) +    g2xy = defaultdict(set) +    for x, y in xy: +        y = -y +        gx = xy2g[x] +        gy = xy2g[y] +        if gx == gy != 0: +            continue +        elif gx != 0 != gy:  # merge +            if len(g2xy[gx]) < len(g2xy[gy]): +                gx, gy = gy, gx +            for xy in g2xy[gy]: +                xy2g[xy] = gx +            g2xy[gx] |= g2xy[gy] +            g2xy[gy].clear() +        else: +            g = gx or gy or x +            xy2g[x] = xy2g[y] = g +            g2xy[g] |= {x, y} -    for node in edges: -        if not visited[node]: -            li = solve(node) -            m, p = 0, 0 -            for z in li: -                if z < 0: -                    m += 1 -                else: -                    p += 1 -            ans += m * p +    for xys in list(g2xy.values()): +        nx = sum(xy > 0 for xy in xys) +        ny = len(xys) - nx +        ans += nx * ny