2756 SCOI2012 奇怪的遊戲

2021-07-22 18:12:43 字數 3044 閱讀 7404

time limit: 40 sec  

memory limit: 128 mb

submit: 3052  

solved: 840 [

submit][

status][

discuss]

blinker最近喜歡上乙個奇怪的遊戲。 

這個遊戲在乙個 n*m 的棋盤上玩,每個格仔有乙個數。每次 blinker 會選擇兩個相鄰

的格仔,並使這兩個數都加上 1。 

現在 blinker 想知道最少多少次能使棋盤上的數都變成同乙個數,如果永遠不能變成同

乙個數則輸出-1。 

輸入的第一行是乙個整數t,表示輸入資料有t輪遊戲組成。 

每輪遊戲的第一行有兩個整數n和m, 分別代表棋盤的行數和列數。 

接下來有n行,每行 m個數。 

對於每個遊戲輸出最少能使遊戲結束的次數,如果永遠不能變成同乙個數則輸出-1。 2

2 2

1 2

2 3

3 3

1 2 3

2 3 4

4 3 2

2 -1

【資料範圍】 

對於30%的資料,保證  t<=10,1<=n,m<=8 

對於100%的資料,保證  t<=10,1<=n,m<=40,所有數為正整數且小於1000000000  [

submit][

status][

discuss]

如果這個矩形一共有偶數個格仔,那麼顯然可以二分答案

因為你總能找到一些方法把每個格仔的數字累加上去

判斷的話很容易想到用網路流

先把這個矩形二分圖染色

記當前二分now為每個格仔最後的狀態

源點到每個黑點連容量為now - w[i][j]的邊

每個白點到匯點連容量為now - w[i][j]的邊

黑點與白點之間再連邊模擬增加操作

跑一遍最大流

但是奇數的話就沒辦法二分了

列出幾個等式

不妨假設最後每個格仔的元素都是k

記初始時黑點權值和為sx,白點為sy,設黑點tx個,白點ty個

假設一共做了tot次增加操作

由於每個增加操作一定是乙個黑點+1並且乙個白點+1,那麼

sx*tx + tot = k*tx

sy*ty + tot = k*ty

聯立這兩個式子消去tot,發現k的值唯一確定

再判斷一下就好

#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;

const int maxn = 1e5 + 10;

typedef long long ll;

const ll inf = 1e15;

const int dx[4] = ;

const int dy[4] = ;

struct e

e(int to,ll cap,ll flow): to(to),cap(cap),flow(flow) {}

}edgs[maxn];

int t,tot,cnt,s,t,n,m,max,cnt,a[55][55],co[55][55]

,vis[maxn],w[55][55],l[maxn],cur[maxn];

ll goal,sum[2],p[2];

vector v[maxn];

queue q;

void color()

t = ++tot;

sum[0] = w[1][1]; p[0] = 1;

sum[1] = p[1] = 0;

co[1][1] = 0;

for (int i = 2; i <= m; i++)

for (int i = 2; i <= n; i++)

for (int i = 2; i <= n; i++)

for (int j = 2; j <= m; j++)

}void add(int x,int y,ll cap)

bool bfs()

} return vis[t] == cnt;

}ll dicnic(int x,ll a)

if (!flow) l[x] = -1;

return flow;

}void clear()

void build(ll now,ll &g0,ll &g1)

g0 += cap;

}else add(a[i][j],t,cap),g1 += cap;

} }bool judge(ll now)

ll maxflow = 0;

while (bfs())

clear();

goal = g1;

return g1 == maxflow;

}void solve1()

if (judge(l)) printf("%lld\n",goal);

else if (judge(r)) printf("%lld\n",goal);

else puts("-1");

}void solve2()

}int main()

return 0;

}

bzoj2756 SCOI2012 奇怪的遊戲

description blinker最近喜歡上乙個奇怪的遊戲。這個遊戲在乙個 n m 的棋盤上玩,每個格仔有乙個數。每次 blinker 會選擇兩個相鄰 的格仔,並使這兩個數都加上 1。現在 blinker 想知道最少多少次能使棋盤上的數都變成同乙個數,如果永遠不能變成同 乙個數則輸出 1。inp...

bzoj2756 SCOI2012 奇怪的遊戲

description blinker最近喜歡上乙個奇怪的遊戲。這個遊戲在乙個 n m 的棋盤上玩,每個格仔有乙個數。每次 blinker 會選擇兩個相鄰的格仔,並使這兩個數都加上 1。現在 blinker 想知道最少多少次能使棋盤上的數都變成同乙個數,如果永遠不能變成同乙個數則輸出 1。input...

bzoj2756 SCOI2012 奇怪的遊戲

blinker最近喜歡上乙個奇怪的遊戲。這個遊戲在乙個 n m 的棋盤上玩,每個格仔有乙個數。每次 blinker 會選擇兩個相鄰的格仔,並使這兩個數都加上 1。現在 blinker 想知道最少多少次能使棋盤上的數都變成同乙個數,如果永遠不能變成同乙個數則輸出 1。輸入的第一行是乙個整數t,表示輸入...