#include <bits/stdc++.h>
using namespace std;
long long find(vector<long long> &P, long long a) {
  if (a == P[a]) return a;
  return P[a] = find(P, P[a]);
}
void un_(vector<long long> &P, vector<long long> &S, long long a, long long b) {
  a = find(P, a);
  b = find(P, b);
  if (a != b) {
    if (S[a] < S[b]) swap(a, b);
    P[b] = a;
    S[a] += S[b];
  }
}
class hashf {
 public:
  long long operator()(const pair<long long, long long> &p) const {
    long long a = p.first, b = p.second;
    return a * a * b + a * b + a * b * b;
  }
};
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  vector<bool> yax(1001, 0);
  vector<bool> xax(1001, 0);
  vector<long long> xind(1001), yind(1001);
  long long n;
  cin >> n;
  vector<long long> A(n);
  vector<long long> P(n);
  for (long long i = 0; i < n; i++) P[i] = i;
  vector<long long> S(n, 1);
  vector<vector<long long>> edge(n, vector<long long>(2));
  unordered_map<pair<long long, long long>, long long, hashf> m;
  long long count = 0;
  for (long long i = 0; i < n; i++) {
    long long x, y;
    cin >> x >> y;
    edge[i][0] = x, edge[i][1] = y;
    m[{x, y}] = i;
  }
  for (long long i = 0; i < n; i++) {
    long long x = edge[i][0], y = edge[i][1];
    if (!(xax[x] == 0 and yax[y] == 0)) {
      if (xax[x] == 1) {
        int j = xind[x];
        un_(P, S, m[{x, y}], m[{edge[j][0], edge[j][1]}]);
      }
      if (yax[y] == 1) {
        int j = yind[y];
        un_(P, S, m[{x, y}], m[{edge[j][0], edge[j][1]}]);
      }
      yax[y] = xax[x] = 1;
      xind[x] = yind[y] = i;
    } else {
      yind[y] = i, xind[x] = i;
      yax[y] = xax[x] = 1;
    }
  }
  for (long long i = 0; i < n; i++)
    if (P[i] == i) count++;
  cout << count - 1 << endl;
}
