#include #include #define rep(i,n) for(int i=0;i vi; typedef vector vl; typedef vector> vvi; typedef vector> vvl; typedef long double ld; typedef pair P; ostream& operator<<(ostream& os, const modint& a) {os << a.val(); return os;} template ostream& operator<<(ostream& os, const static_modint& a) {os << a.val(); return os;} template istream& operator>>(istream& is, vector& v){int n = v.size(); assert(n > 0); rep(i, n) is >> v[i]; return is;} template ostream& operator<<(ostream& os, const pair& p){os << p.first << ' ' << p.second; return os;} template ostream& operator<<(ostream& os, const vector& v){int n = v.size(); rep(i, n) os << v[i] << (i == n - 1 ? "\n" : " "); return os;} template ostream& operator<<(ostream& os, const vector>& v){int n = v.size(); rep(i, n) os << v[i] << (i == n - 1 ? "\n" : ""); return os;} int main(){ int h, w; cin >> h >> w; int n = h * (h + w); mcf_graph graph(n + 2); int sv = n; int tv = n + 1; rep(y, h) rep(x, h + w){ int from = y * (h + w) + x; if(y < h - 1){ int to = (y + 1) * (h + w) + x; graph.add_edge(from, to, 100, 1); graph.add_edge(to, from, 100, 1); } if(x < h + w - 1){ int to = y * (h + w) + (x + 1); graph.add_edge(from, to, 100, 1); graph.add_edge(to, from, 100, 1); } if(y < h - 1 and x < h + w - 1){ int to = (y + 1) * (h + w) + (x + 1); graph.add_edge(from, to, 100, 1); graph.add_edge(to, from, 100, 1); } } rep(i, w){ int y, x; cin >> y >> x; x--; y--; graph.add_edge(sv, y * (h + w) + x, 1, 0); } rep(x, w){ graph.add_edge(x, tv, 1, 0); } auto [cap, cost] = graph.flow(sv, tv); // cout << cap << ' ' << cost << "\n"; cout << cost << "\n"; return 0; }