class UnionFind
  attr :parent, :rank
  def initialize
    @parent = Hash.new
    @rank = Hash.new
  end
  def make(x)
    @parent[x] = x
    @rank[x] = 0
  end
  def union(a, b)
    x, y = find(a), find(b)
    x, y = y, x if @rank[x] < @rank[y]
    @parent[y] = x
    @rank[x] += 1 if @rank[x] == @rank[y]
  end
  def find(x)
    @parent[x] == x ? x : @parent[x] = find(@parent[x])
  end
  def size
    @parent.keys.map{|k| find(k)}.sort.uniq.size
  end
end

class Point
  attr :id, :x, :y
  def initialize(id, x, y)
    @id, @x, @y = id, x, y
  end
end

require 'set'

P = gets.to_i.times.map{|i| Point.new(i, *gets.split.map(&:to_i))}

uf = UnionFind.new
P.each do |p|
  uf.make(p.id)
end
P.sort{|l, r| l.x <=> r.x}.each_cons(2) do |l, r|
  uf.union(l.id, r.id) if l.x == r.x
end
P.sort{|l, r| l.y <=> r.y}.each_cons(2) do |l, r|
  uf.union(l.id, r.id) if l.y == r.y
end

X = Hash.new{|h, k| h[k] = Set.new}
Y = Hash.new{|h, k| h[k] = Set.new}
G = Set.new
P.each do |p|
  g = uf.find(p.id)
  G << g
  X[g] << p.x
  Y[g] << p.y
end
p G.map{|g| X[g].size * Y[g].size}.inject(:+) - P.size
