#include <bits/stdc++.h>
using namespace std;
struct _ {
  ios_base::Init i;
  _() { ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL); }
} _;
const int maxn = 1e3;
int main() {
  int n;
  cin >> n;
  vector<pair<int, int>> pts(n);
  for (int i = 0; i <= n - 1; i++) cin >> pts[i].first >> pts[i].second;
  vector<vector<pair<int, int>>> parent(
      maxn + 1, vector<pair<int, int>>(maxn + 1, {0, 0}));
  vector<vector<int>> sze(maxn + 1, vector<int>(maxn + 1, 1));
  for (int i = 0; i <= maxn; i++) {
    for (int j = 0; j <= maxn; j++) parent[i][j] = {i, j};
  }
  function<pair<int, int>(pair<int, int>)> find_parent =
      [&](pair<int, int> u) -> pair<int, int> {
    if (parent[u.first][u.second] == u) return u;
    return parent[u.first][u.second] = find_parent(parent[u.first][u.second]);
  };
  auto merge = [&](pair<int, int> u, pair<int, int> v) -> bool {
    u = find_parent(u);
    v = find_parent(v);
    if (u != v) {
      if (sze[u.first][u.second] < sze[v.first][v.second]) swap(u, v);
      parent[v.first][v.second] = u;
      sze[u.first][u.second] += sze[v.first][v.second];
      return true;
    }
    return false;
  };
  for (auto p1 : pts) {
    for (auto p2 : pts) {
      if (p1 == p2) continue;
      if (p1.first == p2.first or p1.second == p2.second) merge(p1, p2);
    }
  }
  int cnt = 0;
  for (auto p : pts) {
    if (find_parent(p) == p) cnt++;
  }
  cout << cnt - 1;
  return 0;
}
