#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define NUM 205

struct Info{

	int W,H;
};

int V; //頂点数
vector<int> G[NUM];
int match[NUM];
bool used[NUM];
Info info[105];

void add_edge(int from,int to){
	G[from].push_back(to);
	G[to].push_back(from);
}

int dfs(int node_id){
	used[node_id] = true;

	for(int i = 0; i < G[node_id].size(); i++){
		int adj_node_id = G[node_id][i],pair_id = match[adj_node_id];
		if((pair_id < 0)||
				(used[pair_id] == false && dfs(pair_id) == true)){

			match[node_id] = adj_node_id;
			match[adj_node_id] = node_id;
			return true;
		}
	}
	return false;
}


int bipartie_matching(){
	int ret = 0;
	for(int i = 0; i < V; i++)match[i] = -1; //ペアなしにしておく
	for(int node_id = 0; node_id < V; node_id++){
		if(match[node_id] < 0){ //node_idにペアがいない場合
			for(int i = 0; i < V; i++)used[i] = false;
			if(dfs(node_id)){ //増加パスが存在する場合
				ret++;
			}
		}
	}
	return ret;
}


int main(){

	int N;
	scanf("%d",&N);

	for(int i = 0; i < N; i++){

		scanf("%d %d",&info[i].W,&info[i].H);
	}

	for(int from = 0; from < N; from++){
		for(int to = 0; to < N; to++){
			if((info[from].W < info[to].W && info[from].H < info[to].H) ||
					(info[from].H < info[to].W && info[from].W < info[to].H)){
				add_edge(from,N+to);
			}
		}
	}

	V = 2*N;

	printf("%d\n",N-bipartie_matching());

	return 0;
}

