#include #define REP(A,B) for(int (A)=0;(A)<(B);(A)++) using namespace std; #define pb push_back #define mp make_pair int XS[2222], YS[2222]; map< pair, int > M; vector nxt[2222]; struct Edge { int dest,cost,next; Edge(int dest, int cost, int next): dest(dest), cost(cost), next(next) {} }; struct Network { int N,src,sink; vector last,dist; vector e; Network(int N, int src, int sink): N(N), src(src), sink(sink),last(N), dist(N) { fill(last.begin(), last.end(), -1); } void addEdge(int x, int y, int xy, int yx) { e.pb(Edge(y, xy, last[x])); last[x] = (int)e.size()-1; e.pb(Edge(x, yx, last[y])); last[y] = (int)e.size()-1; } bool getPath() { fill(dist.begin(), dist.end(), -1); queue q; q.push(src); dist[src] = 0; while(!q.empty()) { int curr = q.front(); q.pop(); for(int i = last[curr]; i != -1; i = e[i].next) { if(e[i].cost > 0 && dist[e[i].dest] == -1) { dist[e[i].dest] = dist[curr]+1; q.push(e[i].dest); } } } return dist[sink] != -1; } int dfs(int curr, int flow) { if(curr == sink) return flow; int rt = 0; for(int i = last[curr]; i != -1; i = e[i].next) { if(e[i].cost > 0 && dist[e[i].dest] == dist[curr] +1) { int res = dfs(e[i].dest, min(flow, e[i].cost)); rt += res; e[i].cost -= res; e[i^1].cost += res; flow -= res; if(flow == 0) break; } } return rt; } int getFlow() { int res = 0; while(getPath()) { res += dfs(src, 1<<30); } return res; } }; /* int D[2222][2]; int dp[2222][2]; int dfs(int u, int cantake, int d) { vis[u][cantake] = 1; int& ans = dp[u][cantake]; if(ans == -1) { ans = 0; if(cantake) { ans = 1; for(int v : nxt[u]) { if(vis[v][0]) continue; ans += dfs(v, 0); } } int nevezmu = 0; for(int v : nxt[u]) { if(vis[v][1]) continue; nevezmu += dfs(v, 1); } ans = max(ans, nevezmu); } return ans; }*/ int main() { int n; while(scanf("%d", &n) == 1) { M.clear(); REP(i, n) { scanf("%d%d", XS+i, YS+i); M[mp(XS[i],YS[i])] = i+2; //printf("%d %d = %d\n", XS[i], YS[i], i+2); } REP(i,n+10) nxt[i].clear(); Network net(2*n, 0, 1); for(auto p : M) { int r = p.first.first, c = p.first.second; int vI = p.second; int comp = (r+c)%2; if(comp == 0) { net.addEdge(0, vI, 1, 0); } else net.addEdge(vI, 1, 1, 0); if(comp == 0) { for(int dx = -1; dx <= 1; dx++) { for(int dy = -1; dy <= 1; dy++) { if(abs(dx)+abs(dy) == 1) { int nr = r+dx, nc = c+dy; if(M.count(mp(nr,nc))) { int v2 = M[mp(nr,nc)]; // nxt[vI].pb(v2); // nxt[v2].pb(vI); net.addEdge(vI, v2, 1, 0); //printf("%d %d\n", vI, v2); } } } } } } /*int ans = 0; REP(i, n) { REP(j, n) REP(k, 2) vis[j][k] =0, dp[j][k] = -1; ans = max(ans, dfs(i, 1)); } printf("%d\n", ans);*/ printf("%d\n", n-net.getFlow()); } return 0; }