#include <bits/stdc++.h>
using namespace std;
using llong = long long;
using vll = vector<llong>;
using vl = vector<long>;
using vi = vector<int>;
using vvi = vector<vi>;
llong gcd(llong a, llong b) {
  while (a != 0) {
    b = b % a;
    swap(a, b);
  }
  return b;
}
vi prefix_sum(const vi& v) {
  vi res(v.size() + 1, 0);
  for (int i = 0; i < v.size(); ++i) {
    res[i + 1] = res[i] + v[i];
  }
  return res;
}
vi read_vi(int n) {
  vi res(n, 0);
  for (int i = 0; i < n; ++i) {
    cin >> res[i];
  }
  return res;
}
int find(vector<int>& uf, int x) {
  int i = x;
  while (uf[i] != i) {
    i = uf[i];
  }
  uf[x] = i;
  return i;
}
void join(vector<int>& uf, int x, int y) {
  int px = find(uf, x);
  int py = find(uf, y);
  if (px == py) {
    return;
  }
  uf[px] = py;
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  int t;
  cin >> t;
  vector<vector<int>> p(t, vector<int>(2));
  map<int, int> x_map;
  map<int, int> y_map;
  vector<int> uf(t, -1);
  for (int i = 0; i < t; ++i) {
    cin >> p[i][0] >> p[i][1];
    uf[i] = i;
    if (x_map.count(p[i][0]) == 0) {
      x_map[p[i][0]] = i;
    } else {
      join(uf, i, x_map[p[i][0]]);
    }
    if (y_map.count(p[i][1]) == 0) {
      y_map[p[i][1]] = i;
    } else {
      join(uf, i, y_map[p[i][1]]);
    }
  }
  set<int> s;
  for (int i = 0; i < uf.size(); ++i) {
    s.insert(find(uf, i));
  }
  cout << s.size() - 1 << endl;
  return 0;
}
