| 12
 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;
 }
 
 |