#include using namespace std; typedef long long ll; typedef pair pi; typedef vector vi; #define sz(x) ((ll)(x).size()) #define all(x) begin(x), end(x) #define rep(i, a, b) for(int i = a; i < (b); ++i) struct Boar { int x, y; bool operator<(const Boar &rhs) const { return std::tie(x, y) < std::tie(rhs.x, rhs.y); } bool operator>(const Boar &rhs) const { return rhs < *this; } bool operator<=(const Boar &rhs) const { return !(rhs < *this); } bool operator>=(const Boar &rhs) const { return !(*this < rhs); } bool operator==(const Boar &rhs) const { return std::tie(x, y) == std::tie(rhs.x, rhs.y); } bool operator!=(const Boar &rhs) const { return !(rhs == *this); } }; #define SUCCESSFUL 1 int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); cin.exceptions(ios::failbit); int n; cin >> n; vector boars; boars.reserve(n); set non_visited; map> by_x; map> by_y; for (int i = 0; i < n; ++i) { boars.emplace_back(); cin >> boars.back().x >> boars.back().y; by_x[boars.back().x].emplace_back(i); by_y[boars.back().y].emplace_back(i); non_visited.emplace(i); } ll components_cnt = 0; while (!non_visited.empty()) { components_cnt += 1; ll start = *non_visited.begin(); non_visited.erase(non_visited.begin()); vector to_visit{start}; while (!to_visit.empty()) { ll current = to_visit.back(); to_visit.pop_back(); vi& neighbours_x = by_x.at(boars.at(current).x); vi& neighbours_y = by_y.at(boars.at(current).y); for (ll neighbour : neighbours_x) { if (non_visited.erase(neighbour) != SUCCESSFUL) { continue; } to_visit.emplace_back(neighbour); } for (ll neighbour : neighbours_y) { if (non_visited.erase(neighbour) != SUCCESSFUL) { continue; } to_visit.emplace_back(neighbour); } } } cout << components_cnt - 1 << '\n'; }