1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| #include <bits/stdc++.h> #define MAX_N 2000 #define MAX_M 20000 #define INF (1LL<<50) #define mid ((l+r)>>1) using namespace std; typedef long long lnt; template <class T> inline void read(T &x) { x = 0; int c = getchar(), f = 1; for (; !isdigit(c); c = getchar()) if (c == 45) f = -1; for (; isdigit(c); c = getchar()) (x *= 10) += f*(c-'0'); } int nxt[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; int n, m, s, t, cnt, d[MAX_N+5], pr[MAX_N+5], cr[MAX_N+5]; struct node {int v, nxt; lnt c;} E[MAX_M+5]; int col[50][50], c0, c1; lnt a[50][50], s0, s1, mx; int p(int x, int y) {return x*m-m+y;} void init() {s = 0, t = n*m+1, cnt = 0, memset(pr, -1, sizeof pr);} void insert(int u, int v, lnt c) {E[cnt] = (node){v, pr[u], c}, pr[u] = cnt++;} void addedge(int u, int v, lnt c) {insert(u, v, c), insert(v, u, 0);} bool BFS() { queue <int> que; que.push(s); memset(d, -1, sizeof d), d[s] = 0; while (!que.empty()) { int u = que.front(); que.pop(); for (int i = pr[u]; ~i; i = E[i].nxt) { int v = E[i].v; lnt c = E[i].c; if (~d[v] || !c) continue; d[v] = d[u]+1, que.push(v); } } return ~d[t]; } lnt DFS(int u, lnt flow) { if (u == t) return flow; lnt ret = 0; for (int &i = pr[u]; ~i; i = E[i].nxt) { int v = E[i].v; lnt c = E[i].c; if (d[u]+1 != d[v] || !c) continue; lnt tmp = DFS(v, min(flow, c)); E[i].c -= tmp, E[i^1].c += tmp; flow -= tmp, ret += tmp; if (!flow) break; } if (!ret) d[u] = -1; return ret; } void cpy() {for (int i = s; i <= t; i++) cr[i] = pr[i];} void rec() {for (int i = s; i <= t; i++) pr[i] = cr[i];} lnt Dinic() {lnt ret = 0; cpy(); while (BFS()) ret += DFS(s, INF), rec(); return ret;} bool chk(lnt x) { init(); lnt tot = 0; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) if (col[i][j]) addedge(s, p(i, j), x-a[i][j]), tot += x-a[i][j]; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) if (!col[i][j]) addedge(p(i, j), t, x-a[i][j]); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) if (col[i][j]) for (int k = 0; k < 4; k++) { int x = i+nxt[k][0], y = j+nxt[k][1]; if (x < 1 || x > n || y < 1 || y > m) continue; addedge(p(i, j), p(x, y), INF); } return Dinic() == tot; } lnt bi_search(lnt l, lnt r) { lnt ret = -1; while (l <= r) if (!chk(mid)) l = mid+1; else ret = mid, r = mid-1; return ret; } void color() { mx = c0 = c1 = s0 = s1 = 0; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) col[i][j] = (i+j)&1, (col[i][j] ? c1++ : c0++); } int main() { int T; read(T); while (T--) { read(n), read(m), color(); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) read(a[i][j]), mx = max(mx, a[i][j]), (col[i][j] ? s1 += a[i][j] : s0 += a[i][j]); if (c0^c1) { if ((s0-s1)/(c0-c1) >= m && chk((s0-s1)/(c0-c1))) printf("%lld\n", (s0-s1)/(c0-c1)*c0-s0); else puts("-1"); } else { if (s0^s1) puts("-1"); else printf("%lld\n", bi_search(mx, INF)*c0-s0); } } return 0; }
|