#include <bits/stdc++.h>
void dfs(int v, bool marked[], std::vector<int> adjacency_list[]) {
  marked[v] = true;
  for (size_t i = 0; i < adjacency_list[v].size(); ++i) {
    int to = adjacency_list[v][i];
    if (!marked[to]) dfs(to, marked, adjacency_list);
  }
}
int clustersCount(std::vector<int> adjacency_list[], size_t points_count) {
  std::vector<int> cluster;
  bool marked[100] = {0};
  int clusters_count = 0;
  for (size_t i = 0; i < points_count; ++i) {
    if (!marked[i]) {
      ++clusters_count;
      dfs(i, marked, adjacency_list);
    }
  }
  return clusters_count;
}
void fillInAdjacencyList(std::vector<int> adjacency_list[],
                         const std::vector<int>& x, const std::vector<int>& y) {
  size_t points_count = x.size();
  for (size_t i = 0; i != points_count; ++i) {
    for (size_t j = i + 1; j < points_count; ++j) {
      if (x[i] == x[j] || y[i] == y[j]) {
        adjacency_list[i].push_back(j);
        adjacency_list[j].push_back(i);
      }
    }
  }
}
int main() {
  size_t points_count = 0;
  scanf("%d", &points_count);
  std::vector<int> point_x(points_count);
  std::vector<int> point_y(points_count);
  for (size_t i = 0; i != points_count; ++i) {
    scanf("%d %d", &point_x[i], &point_y[i]);
  }
  std::vector<int> adjacency_list[100];
  fillInAdjacencyList(adjacency_list, point_x, point_y);
  printf("%d", clustersCount(adjacency_list, points_count) - 1);
  return 0;
}
