由数据范围容易想到网络流。由于操作只是对于棋盘上相邻两格,容易想到给其黑白染色。

  假设已经知道最后要变成什么数。那么给黑白点之间连边,其流量则表示同时增加的次数,再用源汇给其限流为需要增加的数即可。

  考虑最后应该变成什么数。

  如果棋盘中黑白格子数量不同,设最后变成的数是x,则x*黑格数量-黑格数字和=x*白格数量-白格数字和,若黑格数量多即x=黑格数字和-白格数字和。直接变为最大值是不一定合法的。

  否则首先黑白格子内权值和应相同,否则无解。如果变成某个数是合法的,变的更大也是合法的。那么二分最后变成的数即可。因为最终方案中并不一定存在能恰好覆盖整个棋盘的操作,所以直接变为最大数是错的。注意二分上界需要开的非常大。

  无数次死于long long。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 42
#define S 0
#define T 1601
#define inf 2000000000000
int test,n,m,p[N*N],a[N][N],t;
int d[N*N],q[N*N],cur[N*N];
bool flag[N*N];
long long ans;
struct data{int to,nxt;long long cap,flow;
}edge[N*N<<];
void addedge(int x,int y,long long z)
{
t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].cap=z,edge[t].flow=,p[x]=t;
t++;edge[t].to=x,edge[t].nxt=p[y],edge[t].cap=,edge[t].flow=,p[y]=t;
}
int trans(int x,int y){return (x-)*m+y;}
bool bfs()
{
memset(d,,sizeof(d));d[S]=;
int head=,tail=;q[]=S;
do
{
int x=q[++head];
for (int i=p[x];~i;i=edge[i].nxt)
if (d[edge[i].to]==-&&edge[i].flow<edge[i].cap)
{
d[edge[i].to]=d[x]+;
q[++tail]=edge[i].to;
}
}while (head<tail);
return ~d[T];
}
long long work(int k,long long f)
{
if (k==T) return f;
long long used=;
for (int i=cur[k];~i;i=edge[i].nxt)
if (d[k]+==d[edge[i].to])
{
long long w=work(edge[i].to,min(edge[i].cap-edge[i].flow,f-used));
edge[i].flow+=w,edge[i^].flow-=w;
if (edge[i].flow<edge[i].cap) cur[k]=i;
used+=w;if (used==f) return f;
}
if (used==) d[k]=-;
return used;
}
void dinic()
{
ans=;
while (bfs())
{
memcpy(cur,p,sizeof(p));
ans+=work(S,inf);
}
}
bool check(long long k,long long lim)
{
t=-;memset(p,,sizeof(p));
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
if (i+j&)
{
addedge(S,trans(i,j),k-a[i][j]);
if (i>) addedge(trans(i,j),trans(i-,j),inf);
if (i<n) addedge(trans(i,j),trans(i+,j),inf);
if (j>) addedge(trans(i,j),trans(i,j-),inf);
if (j<m) addedge(trans(i,j),trans(i,j+),inf);
}
else addedge(trans(i,j),T,k-a[i][j]);
dinic();
return ans==lim;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj2756.in","r",stdin);
freopen("bzoj2756.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
test=read();
while (test--)
{
n=read(),m=read();int v=;
long long sumx=,sumy=;
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
{
v=max(v,a[i][j]=read());
if (i+j&) sumx+=a[i][j];
else sumy+=a[i][j];
}
long long tot=-;
if ((n&)&&(m&)) tot=sumy-sumx>=v?(check(sumy-sumx,(sumy-sumx)*n*m-sumx-sumy>>)?sumy-sumx:-):-;
else
{
if (sumx==sumy)
{
long long l=v,r=inf;
while (l<=r)
{
long long mid=l+r>>;
if (check(mid,mid*n*m-sumx-sumy>>)) tot=mid,r=mid-;
else l=mid+;
}
}
}
if (tot==-) cout<<-<<endl;
else cout<<(tot*n*m-sumx-sumy>>)<<endl;
}
return ;
}

BZOJ2756 SCOI2012奇怪的游戏(二分答案+最大流)的更多相关文章

  1. Bzoj2756 [SCOI2012]奇怪的游戏

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

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

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

  3. bzoj 2756 [SCOI2012]奇怪的游戏 二分+网络流

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

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

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

  5. BZOJ2756 [SCOI2012]奇怪的游戏 【网络流 + 二分】

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

  6. P5038 [SCOI2012]奇怪的游戏 二分+网络流

    $ \color{#0066ff}{ 题目描述 }$ Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 \(N \times M\) 的棋盘上玩,每个格子有一个数.每次\(Blinker\)会 ...

  7. BZOJ.2756.[SCOI2012]奇怪的游戏(二分 黑白染色 最大流ISAP)

    题目链接 \(Description\) \(Solution\) 这种题当然要黑白染色.. 两种颜色的格子数可能相同,也可能差1.记\(n1/n2\)为黑/白格子数,\(s1/s2\)为黑/白格子权 ...

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

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

  9. 洛谷$P5038\ [SCOI2012]$奇怪的游戏 二分+网络流

    正解:二分+网络流 解题报告: 传送门$QwQ$ 这种什么,"同时增加",长得就挺网络流的$QwQ$?然后看到问至少加多少次,于是考虑加个二分呗?于是就大体确定了做题方向,用的网络 ...

随机推荐

  1. java.lang.NoClassDefFoundError: org.androidpn.client.PersistentConnectionListener

    在运行AndroidpnClient项目时出现了java.lang.NoClassDefFoundError: org.androidpn.client.PersistentConnectionLis ...

  2. 二,ESP8266 GPIO和SPI和定时器和串口(基于Lua脚本语言)

    https://www.cnblogs.com/yangfengwu/p/7514336.html 我们写lua用这个软件 如果点击的时候提示安装,,安装就行,,如果没有提示呢可以,按照下面链接的提示 ...

  3. SVN之 trunk, branches and tags意义

    --简单的对照 SVN的工作机制在某种程度上就像一颗正在生长的树: 一颗有树干和很多分支的树 分支从树干生长出来.而且细的分支从相对较粗的树干中长出 一棵树能够仅仅有树干没有分支(可是这样的情况不会持 ...

  4. 20155331《网路对抗》Exp8 WEB基础实践

    20155331<网路对抗>Exp8 WEB基础实践 基础问题回答 什么是表单 表单在网页中主要负责数据采集功能.一个表单有三个基本组成部分: 表单标签,这里面包含了处理表单数据所用CGI ...

  5. Java技术——String类为什么是不可变的

    0. 前言   如果一个对象,在它创建完成之后不能再改变它的状态,包括对象内的成员变量.基本数据类型的值等等.那么这个对象就是不可变的.众所周知String类就是不可变的.转载请注明出处为SEU_Ca ...

  6. 【php增删改查实例】第四节 -自己 DIY 一个数据库管理工具

    本节介绍如何自己DIY一个数据库管理工具,可以在页面输入sql 进行简单的增删改查操作. 首先,找到xampp的安装目录,打开htdocs: 新建一个php文件,名称为 mysqladmin.php ...

  7. CF 55 D. Beautiful numbers

    D. Beautiful numbers 链接 题意: 求[L,R]中多少个数字可以整除它们的每一位上的数字. 分析: 要求模一些数字等于0等价于模它们的lcm等于0,所以可以记录当前出现的数字的lc ...

  8. libgdx学习记录1——图片显示Texture

    libgdx底层采用opengl渲染,对图片进行了优化处理,与android原生态的bitmap不太一样. 相比而言,效率要高一些,不过只支持png,jpg,bmp三种格式. 显示中,一般将图片放在a ...

  9. CS50.2

    1,ssd硬盘(solid state disk),固态硬盘,固盘. 2,把电磁信号转化为0或者1 ps:记得吧图给加上 反向即从磁盘中得到数据 3,软盘,floppy disk.早期使用的一种存储. ...

  10. Revit二次开发-根据视图阶段(Phase)创建房间

    最近开发业务中,有一个自动创建房间的功能,很自然的想到了Document.NewRooms2方法.但是当前功能的特殊之处在于,Revit项目视图是分阶段(Phase)的,不同阶段的房间是互相独立的. ...