#include #include #include #include #include using namespace std; typedef int LL; struct Edge { int u, v; LL cap, flow; Edge() {} Edge(int u, int v, LL cap): u(u), v(v), cap(cap), flow(0) {} }; struct Dinic { int N; vector E; vector> g; vector d, pt; Dinic(int N): N(N), E(0), g(N), d(N), pt(N) {} void AddEdge(int u, int v, LL cap) { if (u != v) { E.emplace_back(u, v, cap); g[u].emplace_back(E.size() - 1); E.emplace_back(v, u, 0); g[v].emplace_back(E.size() - 1); } } bool BFS(int S, int T) { queue q({S}); fill(d.begin(), d.end(), N + 1); d[S] = 0; while(!q.empty()) { int u = q.front(); q.pop(); if (u == T) break; for (int k: g[u]) { Edge &e = E[k]; if (e.flow < e.cap && d[e.v] > d[e.u] + 1) { d[e.v] = d[e.u] + 1; q.emplace(e.v); } } } return d[T] != N + 1; } LL DFS(int u, int T, LL flow = -1) { if (u == T || flow == 0) return flow; for (int &i = pt[u]; i < g[u].size(); ++i) { Edge &e = E[g[u][i]]; Edge &oe = E[g[u][i]^1]; if (d[e.v] == d[e.u] + 1) { LL amt = e.cap - e.flow; if (flow != -1 && amt > flow) amt = flow; if (LL pushed = DFS(e.v, T, amt)) { e.flow += pushed; oe.flow -= pushed; return pushed; } } } return 0; } LL MaxFlow(int S, int T) { LL total = 0; while (BFS(S, T)) { fill(pt.begin(), pt.end(), 0); while (LL flow = DFS(S, T)) total += flow; } return total; } }; Dinic* dinic; int par[10005]; int find(int x) { return par[x] == x ? x : (par[x] = find(par[x])); } void merge(int x, int y) { par[find(x)] = find(y); } int r, c; string g[105]; int main() { cin >> r >> c; for(int i = 0; i < r; i++) cin >> g[i]; iota(par, par+r*c, 0); for(int i = 0; i < r; i++) { for(int j = 0; j < c; j++) { if(i+1 outside; set ones, zeroes; dinic = new Dinic(r*c+2); for(int i = 0; i < r; i++) for(int j = 0; j < c; j++) { if(i == 0 || i == r-1 || j == 0 || j == c-1) outside.insert(find(i*c+j)); } set> edges; for(int i = 0; i < r; i++) for(int j = 0; j < c; j++) { if(i+1 < r && g[i][j] != g[i+1][j]) { int lhs = find(i*c+j); int rhs = find(i*c+c+j); bool force = true; if(outside.count(lhs) || outside.count(rhs)) force = false; if(g[i][j] == '1') swap(lhs, rhs); if(edges.count(make_pair(lhs, rhs))) force = false; if(force) { edges.emplace(lhs, rhs); if(!ones.count(lhs)) { ones.insert(lhs); dinic->AddEdge(r*c, lhs, 1); } dinic->AddEdge(lhs, rhs, 1); if(!zeroes.count(rhs)) { zeroes.insert(rhs); dinic->AddEdge(rhs, r*c+1, 1); } } } if(j+1 < c && g[i][j] != g[i][j+1]) { int lhs = find(i*c+j); int rhs = find(i*c+1+j); bool force = true; if(outside.count(lhs) || outside.count(rhs)) force = false; if(g[i][j] == '1') swap(lhs, rhs); if(edges.count(make_pair(lhs, rhs))) force = false; if(force) { edges.emplace(lhs, rhs); if(!ones.count(lhs)) { ones.insert(lhs); dinic->AddEdge(r*c, lhs, 1); } dinic->AddEdge(lhs, rhs, 1); if(!zeroes.count(rhs)) { zeroes.insert(rhs); dinic->AddEdge(rhs, r*c+1, 1); } } } } cout << outside.size() + dinic->MaxFlow(r*c, r*c+1) << "\n"; }