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 Haskell (GHC 7.10.3) (judge verdict: Accepted)

-- https://github.com/minoki/my-atcoder-solutions
-- {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE BangPatterns #-}
import Data.Char (isSpace)
-- import Data.Int
import Data.List (unfoldr)
import Control.Monad
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as VM
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Unboxed.Mutable as UM
import qualified Data.ByteString.Char8 as BS
import qualified Data.IntMap as IntMap
import qualified Data.IntSet as IntSet
import Control.Monad.ST

main = do
  n <- readLn
  points <- U.replicateM n $ do
    [x,y] <- unfoldr (BS.readInt . BS.dropWhile isSpace) <$> BS.getLine
    return (x,y)
  let b = 1 + (U.maximum $ U.map fst points)
  let m0 :: IntMap.IntMap IntSet.IntSet
      m0 = U.foldr' (\(x,y) -> IntMap.insertWith IntSet.union x (IntSet.singleton y)) IntMap.empty points
      m1 :: IntMap.IntMap IntSet.IntSet
      m1 = U.foldr' (\(x,y) -> IntMap.insertWith IntSet.union y (IntSet.singleton x)) IntMap.empty points
      m0e :: V.Vector IntSet.IntSet
      m0e = V.fromList $ IntMap.elems m0
      m0a :: V.Vector (Int, IntSet.IntSet)
      m0a = V.fromList $ IntMap.assocs m0
      resultR :: U.Vector Int
      resultS :: V.Vector IntSet.IntSet
      resultN :: U.Vector Int
      (resultR, resultS, resultN) = runST $ do
        root <- U.thaw $ U.enumFromN 0 b
        ss <- VM.replicate b IntSet.empty
        forM_ (IntMap.assocs m0) $ \(k,v) -> VM.write ss k v
        numberOfElements <- UM.replicate b 1
        let getRoot !i = do
              !j <- UM.read root i
              if i == j
                then return i
                else do k <- getRoot j
                        UM.write root i k
                        return k
            unify !i !j = do
              !i' <- getRoot i -- []
              !j' <- getRoot j -- []
              if i' == j'
                then return ()
                else do
                let !k = min i' j'
                UM.write root i' k
                UM.write root j' k
                s1 <- VM.read ss i'
                s2 <- VM.read ss j'
                VM.write ss k $! IntSet.union s1 s2
                n1 <- UM.read numberOfElements i'
                n2 <- UM.read numberOfElements j'
                UM.write numberOfElements k (n1 + n2)
        -- let n = V.length m0e
        forM_ (IntMap.elems m1) $ \t -> do
          let t0:ts = IntSet.toList t
          forM_ ts $ \j ->
            unify t0 j
{-
        forM_ [0..n-1] $ \i -> do
          let s = m0e V.! i
          forM_ [i+1..n-1] $ \j -> do
            let t = m0e V.! j
            unless (IntSet.null $ IntSet.intersection s t) $ do
              unify i j
-}
        liftM3 (,,) (U.freeze root) (V.freeze ss) (U.freeze numberOfElements)
        {-
        foldM (\x -> fmap (+ x)) 0 [ do k <- UM.read root i
                                        if i == k
                                          then IntSet.size <$> VM.read ss i
                                          else return 0
                                   | i <- [0..n-1]]
-}
  --print resultR
  --print resultS
  -- let n' = V.length m0e
  let l = sum [IntSet.size (resultS V.! i) * resultN U.! i | i <- [0..b-1], resultR U.! i == i]
  -- print l
  print $ l - n
  -- print $ result - n
  {-
  let (_,l,s) = IntMap.foldr (\s (i,m,t) -> let !m' = m + i * IntSet.size (IntSet.difference s t) + IntSet.size (IntSet.difference t s)
                                                !u = IntSet.union s t
                                                !i' = i + 1
                                            in (i', m', u)) (0, 0, IntSet.empty) m0
  print $ l
-}