#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define mod 1000000007
#define fi first
#define sc second
#define rep(i,x) for(int i=0;i<x;i++)
#define repn(i,x) for(int i=1;i<=x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())

int par[40005],ran[40005];
void init(){ for(int i=0;i<40005;i++) par[i] = i; }
int find(int x){ if(x == par[x]) return x; else return par[x] = find(par[x]); }
void unite(int x,int y){
	x = find(x); y = find(y); if(x==y) return;
	if(ran[x] < ran[y]) par[x] = y;
	else{
		par[y] = x;
		if(ran[x] == ran[y]) ran[x]++;
	}
}
bool same(int x,int y){ return find(x)==find(y); }

vector<int>X[100005],Y[100005];
bool peri;
int main(){
	int n,w,h; scanf("%d%d%d",&n,&w,&h);
	rep(i,n){
		int a,b; scanf("%d%d",&a,&b);
		X[a].pb(i);
		Y[b].pb(i);
		if(a == 1 || a == w || b == 1 || b == h) peri = 1;
	}
	init();
	rep(i,100005){
		rep(j,X[i].size()){
			if(j) unite(X[i][j-1],X[i][j]);
		}
		rep(j,Y[i].size()){
			if(j) unite(Y[i][j-1],Y[i][j]);
		}
		
	}
	int cmp = 0;
	rep(i,n) if(find(i) == i) cmp++;
	int ans = n+cmp-1;
	if(cmp == 1 || peri) ans--;
	cout<<ans<<endl;
}
