2756: [SCOI2012] Strange game time limit:40 Sec Memory limit:128 MB
submit:2571 solved:685
[Submit] [Status] [Discuss] Description
Blinker recently enjoyed a strange game.
This game is played on a n*m board with a number per grid. Each blinker will select two adjacent
Grid and add 1 to these two numbers.
Now blinker want to know at least how many times you can make the number on the board become the same number, if you can never become the same
A number is output-1.
Input
The first line of input is an integer t, which indicates that the input data has a T-wheel game composition.
The first line of each game has two integers n and m, each representing the number of rows and columns of the chessboard.
Next there are n rows, and the number of m per line.
Output
For each game output the minimum number of times the game will end, if you can never become the same number output-1.
Sample Input2
2 2
1 2
2 3
3 3
1 2 3
2 3 4
4 3 2Sample Output2
-1
HINT
"Data Range"
For 30% of data, ensure t<=10,1<=n,m<=8
For 100% of data, guaranteed t<=10,1<=n,m<=40, all numbers are positive integers and less than 1000000000
Consider that the last state has a good property of equal number, so set all the numbers into X. Because each time only the adjacent two lattice plus 1, so after the odd-even division, the two kinds of lattice changes in the same amount.
So we can list the equations.
Borrow Huang Long Blog here
Black and white staining of the board
Set the number of black lattice to NUM1 value and SUM1
Set the number of white lattice to NUM1 value and SUM1
Set to X at the end
The
NUM1 * x–sum1 = num2 * x–sum2
x = (sum1–sum2)/(NUM1–NUM2)
Then classify the discussion
When num1≠num2, you can solve the x and then use the network flow check.
For num1 = num2, it can be found that a valid x k>=x is a valid solution.
Because NUM1 = num2 = (num1 + num2)% 2 = = 0 can construct a layer of full coverage
So you can split x and then check with the network stream
Build diagram:
If Point K is white
Build Edge (S, K, X–v[k])
If the Black
Build side (K, T, X–v[k])
To adjacent Points u, V (U is white)
Build Edge (U, V, INF)
Methods: Using the properties of the last state, set the unknown and list the equations. Then the classification discussion, first to satisfy the equation to have the solution, then can be two-point answer, in check. In fact, if all is legal, can be directly at the end of the state, and then check. The equation is discussed because the solution is different under different conditions.
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm>using namespace STD; #define MAXN 2020#define maxm 8020#define INF 100000000000000lltypedef Long long ll;struct node{int next,to; LL F;} E[MAXM * 2];int head[maxn],cnt = 1,src,sink;int q[maxn],hh,tt,dis[maxn],cur[maxn];int n,m,T,num1,num2,mx; LL sum1,sum2,maxflow,x,ans;int dt[maxn][maxn];inline void adde (int x,int y,ll c) {e[++cnt].to = Y;e[cnt].next = head[x];e[ CNT].F = C;head[x] = cnt;e[++cnt].to = X;e[cnt].next = Head[y];head[y] = cnt;} inline bool BFs () {tt = HH = 0;memset (dis,0,sizeof (dis)); q[tt++] = src, dis[src] = 1;while (hh < TT) {int now = q[hh++ ];for (int i = head[now]; i; i = E[i].next) {if (e[i].f &&!dis[e[i].to]) {q[tt++] = e[i].to;dis[e[i].to] = dis[ Now] + 1;}}} return Dis[sink] > 0;} LL DFS (int now,ll delta) {if (now = = Sink | |!delta) return delta; LL ret = 0;for (int &i = Cur[now]; i; i = E[i].next) {if (e[i].f && Dis[now] + 1 = = Dis[e[i].to]) {ll d =DFS (E[i].to,min (DELTA,E[I].F)); ret + = d, delta-= d;e[i].f-= d, e[i ^ 1].f + = D;if (!delta) return ret;}} if (delta) Dis[now] = -1;return ret;} Inline LL Dinic () {ll flow = 0;while (BFS ()) {for (int i = 1; I <= sink; i++) Cur[i] = Head[i];flow + = DFS (src,inf);} return flow;} inline void init (LL x) {memset (head,0,sizeof (head)), memset (E,0,sizeof (e)), CNT = 1;for (int i = 1; I <= n; i++) {for T j = 1; J <= M; J + +) {if ((i + j) & 1) {Adde ((i-1) * m + j,sink,x-(LL) dt[i][j]);} Else{int now = (i-1) * m + j;adde (SRC, (i-1) * m + j,x-(LL) dt[i][j]), if (i > 1) adde (Now,now-m,inf); if (i < ; N) Adde (Now,now + m,inf), if (J > 1) adde (Now,now-1,inf); if (J < m) Adde (Now,now + 1,inf);}}} int main () {freopen ("Input.txt", "R", stdin), scanf ("%d", &t), while (t--) {ans = sum1 = sum2 = 0, mx = NUM1 = num2 = 0;SC ANF ("%d%d", &n,&m), src = n * m + 1, sink = n * m + 2;for (int i = 1; I <= n; i++) {for (int j = 1; J <= M ; J + +) {scanf ("%d", &dT[I][J]); if ((i + j) & 1) sum2 + = (ll) dt[i][j], num2++;else sum1 + = (ll) dt[i][j], num1++;mx = max (DT[I][J],MX);}} if (num1! = num2) {if (((sum1-sum2)% (LL) (num1-num2))! = 0) {printf (" -1\n"); continue;} x = (sum1-sum2)/(LL) (num1-num2), if (x < MX) {printf (" -1\n"); continue;} init (x); maxflow = Dinic (); if (maxflow + sum1 = = (LL) NUM1 * x) {printf ("%lld\n", Maxflow);} else printf (" -1\n");} Else{ll L = mx, r = inf;//The current number of each is changed to the condition of mid for (int i = 1; i <=; i++) {maxflow = 0; LL mid = (L + R) >> 1;init (mid); maxflow = Dinic (); if (Maxflow + sum1 = (LL) NUM1 * mid) {ans = Maxflow, r = Mid;} else L = mid + 1;} if (!ans) printf (" -1\n"), Else printf ("%lld\n", ans);}} return 0;}
Bzoj 2756 Strange games