#include using namespace std; #define FOR(i,a,b) for (int i = (a); i <= (b); i++) #define FORD(i,a,b) for (int i = (a); i >= (b); i--) #define REP(i,b) for (int i = 0; i < (b); i++) typedef pair pii; const int N = 2000; int n; pii d[N]; const int dx[4] = { 0, 0, -1, 1 }; const int dy[4] = { -1, 1, 0, 0 }; void gen() { n = 7; set exists; d[0] = make_pair(rand() % 10, rand() % 10); exists.insert(d[0]); FOR(i, 1, n-1) { while (true) { int j = rand() % i; int dir = rand() % 4; int nx = d[j].first + dx[dir]; int ny = d[j].second + dy[dir]; pii nxt = make_pair(nx, ny); if (exists.find(nxt) != exists.end()) continue; exists.insert(nxt); d[i] = nxt; break; } } } pair slow() { int best_count = 0, best_mask = 0; REP(mask, 1 << n) { int count = 0; REP(i, n) if (mask & (1 << i)) { count++; pii a = d[i]; REP(j, n) if (mask & (1 << j)) { pii b = d[j]; if(abs(a.first - b.first) + abs(a.second - b.second) == 1) goto END; } } if (count > best_count) { best_count = count; best_mask = mask; } END:; } return make_pair(best_count, best_mask); } bool removed[N]; vector siblings[N]; bool visited[N]; pii fast() { REP(i, n) { removed[i] = false; siblings[i].clear(); visited[i] = false; } map ids; REP(i, n) ids[d[i]] = i; REP(i, n) if (!removed[i]) { REP(j, 4) { pii sib = make_pair(d[i].first + dx[j], d[i].second + dy[j]); if (ids.find(sib) != ids.end()) { siblings[i].push_back(ids[sib]); } } } int ans = 0; int ans_mask = 0; while (true) { REP(i, n) if (!removed[i]) { int count = 0; for (int s : siblings[i]) if (!removed[s]) count++; if (count == 0) { ans++; ans_mask |= 1 << i; removed[i] = true; goto next; } else if (count == 1) { ans++; ans_mask |= 1 << i; removed[i] = true; int ss = -1; for (int s : siblings[i]) if (!removed[s]) ss = s; removed[ss] = true; goto next; } } break; next:; } REP(ii, n) if (!removed[ii] && !visited[ii]) { queue q; q.push(ii); visited[ii] = true; int a = 0, b = 0; int a_mask = 0, b_mask = 0; while (!q.empty()) { int v = q.front(); q.pop(); if ((d[v].first + d[v].second) % 2 == 0) { a++; a_mask |= 1 << v; } else { b++; b_mask |= 1 << v; } for (int s : siblings[v]) if (!removed[s] && !visited[s]) { visited[s] = true; q.push(s); } } if (a > b) { ans += a; ans_mask |= a_mask; } else { ans += b; ans_mask |= b_mask; } } return make_pair(ans, ans_mask); } void display(int best_mask) { int min_x = d[0].first, max_x = d[0].first; int min_y = d[0].second, max_y = d[0].second; map ids; REP(i, n) { ids[d[i]] = i; min_x = min(min_x, d[i].first); max_x = max(max_x, d[i].first); min_y = min(min_y, d[i].second); max_y = max(max_y, d[i].second); } FOR(x, min_x, max_x) { FOR(y, min_y, max_y) { pii xy = make_pair(x, y); if (ids.find(xy) != ids.end()) { int id = ids[xy]; printf("%c", (best_mask & (1 << id)) ? '*' : '.'); } else { printf(" "); } } printf("\n"); } printf("\n"); printf("\n"); } int main() { srand(482); /*int count = 0; for (int tc = 0; ; tc++) { gen(); pii ans = slow(); pii actual = fast(); if (ans.first != actual.first) { printf("\n"); printf("=============================\n"); printf("expected: %d\n", ans.first); printf("actual: %d\n", actual.first); display(ans.second); display(actual.second); count++; if (count >= 10) break; } }*/ while (scanf("%d", &n) == 1) { REP(i, n) { int x, y; scanf("%d%d", &x, &y); d[i] = make_pair(x, y); } pii ans = fast(); printf("%d\n", ans.first); } return 0; }