#include <bits/stdc++.h>
using namespace std;
int dan = 1;
int cnt = 0;
int am = 0;
template <typename T>
class graph {
  map<T, list<T> > l;

 public:
  void addedge(T x, T y) {
    l[x].push_back(y);
    l[y].push_back(x);
  }
  void dfs_helper(T src, map<T, bool> &visited) {
    visited[src] = true;
    dan *= 2;
    for (auto x : l[src]) {
      if (visited[x] == 0) {
        dfs_helper(x, visited);
      }
    }
  }
  void dfs(T src) {
    map<T, bool> visited;
    for (auto x : l) {
      visited[x.first] = false;
    }
    int count = 0;
    for (auto x : l) {
      if (!visited[x.first]) {
        dfs_helper(x.first, visited);
        cnt++;
      }
    }
  }
  void bfs(T src) {
    queue<T> q;
    map<T, int> m;
    for (auto x : l) {
      m[x.first] = INT_MAX;
    }
    q.push(src);
    m[src] = 0;
    while (!q.empty()) {
      T top = q.front();
      q.pop();
      for (auto nbr : l[top]) {
        if (m[nbr] == INT_MAX) {
          q.push(nbr);
          m[nbr] = m[top] + 1;
        }
      }
    }
    for (auto x : l) {
      cout << x.first << " dis from source = " << m[x.first] << endl;
    }
  }
  void print() {
    for (auto p : l) {
      cout << p.first << "-> ";
      for (auto nbr : l.second) {
        cout << nbr << " ";
      }
      cout << endl;
    }
  }
};
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  graph<pair<int, int> > g;
  int n;
  cin >> n;
  pair<int, int> arr[n];
  for (int i = 0; i < n; ++i) {
    cin >> arr[i].first >> arr[i].second;
  }
  for (int i = 0; i < n; i++) {
    for (int j = i; j < n; j++) {
      if (arr[i].first == arr[j].first || arr[i].second == arr[j].second) {
        g.addedge(arr[i], arr[j]);
      }
    }
  }
  g.dfs(arr[0]);
  cout << cnt - 1 << endl;
}
