#include<iostream>
#include<sstream>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cassert>

#define rep(i,n) for(int i=0;i<(int)n;i++)
#define all(c) (c).begin(),(c).end()
#define mp make_pair
#define pb push_back
#define each(i,c) for(__typeof((c).begin()) i=(c).begin();i!=(c).end();i++)
#define dbg(x) cerr<<__LINE__<<": "<<#x<<" = "<<(x)<<endl

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pi;
const int inf = (int)1e9;
const double INF = 1e12, EPS = 1e-9;

int n, h, w, x[40000], y[40000];
int p[40000], flag[40000], c;
int root(int x){
	if(x == p[x]) return x;
	return p[x] = root(p[x]);
}
bool use[40000];
vi tate[100000], yoko[100000];

void merge(int a, int b){
	a = root(a); b = root(b);
	if(a == b) return;
	c--;
	p[a] = b;
	flag[b] |= flag[a];
}
int main(){
	cin >> n >> w >> h;
	rep(i, n){
		cin >> x[i] >> y[i];
		if(x[i] == 1) flag[i] |= 1 << 0;
		if(x[i] == w) flag[i] |= 1 << 1;
		if(y[i] == 1) flag[i] |= 1 << 2;
		if(y[i] == h) flag[i] |= 1 << 3;
		p[i] = i;
		
		tate[x[i] - 1].pb(i);
		yoko[y[i] - 1].pb(i);
	}
	c = n;
	rep(i, 100000){
		if(tate[i].size() > 1) rep(j, tate[i].size() - 1) merge(tate[i][j], tate[i][j + 1]);
		if(yoko[i].size() > 1) rep(j, yoko[i].size() - 1) merge(yoko[i][j], yoko[i][j + 1]);
	}
	int ans = inf, cnt[4] = {};
	rep(i, n){
		int r = root(i);
		if(use[r]) continue;
		use[r] = 1;
		rep(j, 4) if(flag[r] & 1 << j) cnt[j]++;
	}
	rep(i, 4) ans = min(ans, n - 1 + c - cnt[i]);
	if(c == 1) ans = n - 1;
	cout << ans << endl;
	
	return 0;
}