#include using namespace std; using ll = long long; struct coord { ll x = 0, y = 0; vector neighbors; coord() = default; coord(ll x, ll y) : x(x), y(y), neighbors() {} }; int main() { ll n; cin >> n; vector coords(n); for (ll i = 0; i < n; ++i) { ll x, y; cin >> x >> y; coords[i] = coord(x, y); } vector coordIndexes(n); for (ll i = 0; i < n; ++i) { coordIndexes[i] = i; } const auto cmp = [coords](ll first, ll second) { const coord & a = coords[first]; const coord & b = coords[second]; if (a.x != b.x) return a.x < b.x; return a.y < b.y; }; const auto cmp2 = [coords](ll first, ll second) { const coord & a = coords[first]; const coord & b = coords[second]; if (a.y != b.y) return a.y < b.y; return a.x < b.x; }; std::sort(coordIndexes.begin(), coordIndexes.end(), cmp); for (ll i = 1; i < n; ++i) { ll firstIndex = coordIndexes[i]; ll previousIndex = coordIndexes[i-1]; if (coords[previousIndex].x == coords[firstIndex].x) { coords[previousIndex].neighbors.emplace_back(firstIndex); coords[firstIndex].neighbors.emplace_back(previousIndex); } } std::sort(coordIndexes.begin(), coordIndexes.end(), cmp2); for (ll i = 1; i < n; ++i) { ll firstIndex = coordIndexes[i]; ll previousIndex = coordIndexes[i-1]; if (coords[previousIndex].y == coords[firstIndex].y) { coords[previousIndex].neighbors.emplace_back(firstIndex); coords[firstIndex].neighbors.emplace_back(previousIndex); } } vector visited(n, false); ll result = 0; for (ll i = 0; i < n; ++i) { if (visited[i]) continue; ++result; queue q; q.push(i); visited[i] = true; while (!q.empty()) { ll currIndex = q.front(); q.pop(); const coord & currCoord = coords[currIndex]; for (ll x : currCoord.neighbors) { if (visited[x]) continue; q.push(x); visited[x] = true; } } } cout << result - 1 << '\n'; return 0; }