题目

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

题解

我们将原图黑白染色就会发现每次一定是一黑一白+1

那么我们可以分类讨论:

记黑色n1个总和s1,白色n2个总和s2

①若n1 == n2

二者s1 != s2,无论如何也不会相等

二者s1 == s2,用网络流二分检验:

S向其中一种颜色建边,容量为还差的值

同时这种颜色向周围建边,容量INF

另一种颜色向T建边,容量为还差的值

看看是否满流

②若n1 != n2

我们设x为最后的值

由黑白增量相同,可以得到等式:

x∗n1−s1=x∗n2−s2

化简:

x=s1−s2n1−n2

可见x为定值,若x比最大的数小,无解

否则网络流判断一下

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 45,maxm = 1000005;
const LL INF = (1ll << 50);
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 3) + (out << 1) + c - '0'; c = getchar();}
return out * flag;
}
LL s[maxn][maxn],N,M,n1,n2,mx;
LL s1,s2,d[maxn * maxn];
int X[4] = {0,0,-1,1},Y[4] = {-1,1,0,0},c[maxn][maxn];
int h[maxn * maxn],ne,S,T,vis[maxn * maxn],cur[maxn * maxn];
struct EDGE{int to,nxt; LL f;}ed[maxm];
inline void build(int u,int v,LL w){
ed[ne] = (EDGE){v,h[u],w}; h[u] = ne++;
ed[ne] = (EDGE){u,h[v],0}; h[v] = ne++;
}
bool bfs(){
queue<int> q; int u;
for (int i = S; i <= T; i++) d[i] = INF,vis[i] = false;
d[S] = 0; vis[S] = true; q.push(S);
while (!q.empty()){
u = q.front(); q.pop();
Redge(u) if (ed[k].f && !vis[to = ed[k].to]){
d[to] = d[u] + 1; vis[to] = true; q.push(to);
}
}
return vis[T];
}
LL dfs(int u,LL minf){
if (u == T || !minf) return minf;
LL f,flow = 0; int to;
if (cur[u] == -1) cur[u] = h[u];
for (int& k = cur[u]; k; k = ed[k].nxt)
if (d[to = ed[k].to] == d[u] + 1 && (f = dfs(to,min(minf,ed[k].f)))){
ed[k].f -= f; ed[k ^ 1].f += f;
flow += f; minf -= f;
if (!minf) break;
}
return flow;
}
LL maxflow(){
LL flow = 0;
while (bfs()){fill(cur,cur + maxn * maxn,-1); flow += dfs(S,INF);}
return flow;
}
bool check(LL x){
S = 0; T = N * M + 1; ne = 2; memset(h,0,sizeof(h));
LL tot = 0;
REP(i,N) REP(j,M){
if (c[i][j]){
build(S,(i - 1) * M + j,x - s[i][j]),tot += x - s[i][j];
for (int k = 0; k < 4; k++){
int nx = i + X[k],ny = j + Y[k];
if (nx < 1 || ny < 1 || nx > N || ny > M) continue;
build((i - 1) * M + j,(nx - 1) * M + ny,INF);
}
}else build((i - 1) * M + j,T,x - s[i][j]);
}
return tot == maxflow();
}
void solve1(){
LL x = (s1 - s2) / (n1 - n2);
if (x < mx || !check(x)) puts("-1");
else printf("%lld\n",x * n1 - s1);
}
void solve2(){
if (s1 != s2) {puts("-1"); return;}
LL L = mx,R = INF,mid;
while (L <= R){
mid = L + R >> 1;
if (check(mid)) R = mid - 1;
else L = mid + 1;
}
printf("%lld\n",(LL)L * n1 - s1);
}
int main(){
int Tim = read();
while (Tim--){
N = read(); M = read(); n1 = n2 = s1 = s2 = 0; mx = 0;
REP(i,N) REP(j,M) c[i][j] = (i + j ) & 1,s[i][j] = read();
REP(i,N) REP(j,M){
if (c[i][j]) n1++,s1 += s[i][j];
else n2++,s2 += s[i][j];
mx = max(mx,s[i][j]);
}
if (n1 != n2) solve1();
else solve2();
}
return 0;
}

BZOJ2756 [SCOI2012]奇怪的游戏 【网络流 + 二分】的更多相关文章

  1. bzoj2756: [SCOI2012]奇怪的游戏(网络流+分情况)

    2756: [SCOI2012]奇怪的游戏 题目:传送门 题解: 发现做不出来的大难题一点一个网络流 %大佬 首先黑白染色(原来是套路...)染色之后就可以保证每次操作都一定会使黑白各一个各自的值加1 ...

  2. BZOJ 2756: [SCOI2012]奇怪的游戏 网络流/二分

    2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 1594  Solved: 396[Submit][Stat ...

  3. BZOJ2756 SCOI2012奇怪的游戏(二分答案+最大流)

    由数据范围容易想到网络流.由于操作只是对于棋盘上相邻两格,容易想到给其黑白染色. 假设已经知道最后要变成什么数.那么给黑白点之间连边,其流量则表示同时增加的次数,再用源汇给其限流为需要增加的数即可. ...

  4. 【BZOJ2756】奇怪的游戏(二分,网络流)

    [BZOJ2756]奇怪的游戏(二分,网络流) 题面 BZOJ Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blink ...

  5. Bzoj2756 [SCOI2012]奇怪的游戏

    2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 3220  Solved: 886 Description ...

  6. BZOJ2756:[SCOI2012]奇怪的游戏(最大流,二分)

    Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻 的格子,并使这两个数都加上 1. 现在 B ...

  7. 【BZOJ2756】奇怪的游戏(二分,最小割)

    题意: Blinker最近喜欢上一个奇怪的游戏.这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻的格子,并使这两个数都加上 1.现在 Blinker 想知道最 ...

  8. 洛谷5038 [SCOI2012]奇怪的游戏(二分+网络流+判断奇偶)

    寒假的时候就听过这个题.但是一直没有写. qwq 首先,我们发现题目中的图是个网格图,然后每次可以将相邻两个格子加一. 很容易就想到是黑白染色.那么每次操作,就相当于同时操作一个白点,一个黑点. 我们 ...

  9. BZOJ2756 [SCOI2012]奇怪的游戏 最大流

    好久没有写博客了.不过这个博客也没有多少人看 最近在写网络流,为了加深理解,来写一两篇题解. 对整个棋盘进行黑白染色以后可以发现,一次操作就是让二分图的两个点的值分别 \(+1\). 这样,我们就可以 ...

随机推荐

  1. 初探12C碰到的那些“坑”

    一个昏天黑地的早上,刚搭建的系统忽然遭遇严重数据库问题.于是,主要人物闪亮登场了,他们分别是友商人员小灰和DBA小Y. 事情的开始,小Y接到小灰紧急救助电话... 小灰:小Y,我是友商的小灰,刚搭建的 ...

  2. mybatis中oracle转mysql

    刚来公司实习,遇到的第一个任务就是这个,简单记录一下思路过程.人菜的很,没啥参考价值. 测试时: 将现有的oracle库转为mysql: 用的Navicat自带数据传输功能,简单粗暴 出现的问题: 1 ...

  3. Servlet学习笔记04——什么是重定向,servlet生命周期?

    1.重定向 (1)什么是重定向? 服务器通知浏览器访问一个新的地址. 注: 服务器可以通过发送一个302状态码及一个 Location消息头(该消息头的值是一个地址,一般 称之为重定向地址)给浏览器, ...

  4. eCharts.js使用心得

    最近刚刚做了一个项目,需求是使用eCharts实现实时监控,可以动态的增加和删除数据,可以全屏展示,趁着现在还没忘干净,整理一下使用过程中出现的问题和经验.可能有分析的不到位的地方,不喜勿喷! 一.图 ...

  5. windows下使用curl.exe模拟ajax请求

    curl 是一般linux发行版中都带有的小工具,利用这个工具可以很方便的下载文件,我一般使用这个工具来查看某个页面相应的HTTP头信息,在Windows系统中我们也一样可以使用这个工具,如果不需要支 ...

  6. CentOS7 配置环境

    1.安装CentOS 配置环境 (1)虚拟机中安装CentOS,进入系统使用yum命令不止正常执行…… 原因: 需要设置网卡激活 解决方法: vi /etc/sysconfig/network-scr ...

  7. #Python编程从入门到实践#第四章笔记

    #Python编程从入门到实践#第四章笔记   操作列表 ​​​1.遍历列表 使用for循环,遍历values列表 for value in values: print(value) 2.数字列表 使 ...

  8. 顺序链表的C风格实现

    //头文件 #ifndef _SEQLIST_H_ #define _SEQLIST_H_ //定义数据类型 typedef void SeqList; typedef void SeqListNod ...

  9. Diycode开源项目 SitesListFragment分析

    1.效果预览 1.1.网站列表实际界面 1.2.注意这个界面没有继承SimpleRefreshRecycleFragment 前面的话题和新闻继承了SimpleRefreshRecyclerFragm ...

  10. 5 Django-1的路由层(URLconf)

    URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于客户端发来的某个URL调用哪一段逻辑代码 ...