Description:
\(Blinker\)最近喜欢上一个奇怪的游戏。
这个游戏在一个 \(N \times M\) 的棋盘上玩,每个格子有一个数。每次\(Blinker\)会选择两个相邻的格子,并使这两个数都加上\(1\)。
现在\(Blinker\)想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成同一个数则输出\(-1\)。
Solution:
也算是网络流+二分答案的套路题吧
这个人讲得很好,转自
不难看出,对棋盘进行黑白染色之后,每次相加都会使得相邻的一黑一白两个格子同时+1,。
先对所有黑白格子进行统计,处理出\(cnt0\),\(cnt1\)分别代表黑、白格子个数,处理出\(sum0\),\(sum1\)分别代表黑、白格子权值和。
分类讨论如下:
如果\(cnt0=cnt1\)
如果\(sum0\not =sum1\),那么一定不存在合法解
如果\(sum0=sum1\),设最终所有数字都变成\(ans\),发现如果\(ans\)满足,则\(ans+1\)必定也满足(补充:因为此时n,m中必有一个偶数,可以随意给所有数+1),即\(ans\)满足二分性质,因此可以二分答案,网络流判断是否可行。
如果\(cnt0\not =cnt1\)
依旧设最终数字为\(ans\),则有\(cnt0\times ans-sum0=cnt1\times ans-sum1\),化简得\(ans=\frac{sum0-sum1}{cnt0-cnt1}\),只需要检查这个值是否合法即可。
网络流判断可行的方法:
从S向每个黑点连\(ans-Val_{i,j}\)的边,从每个白点向T连\(ans-Val_{i,j}\)的边,相邻的黑点向白点连\(+\infty\)的边,判断是否满流。
#include