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

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

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

  如果棋盘中黑白格子数量不同,设最后变成的数是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. 一个有趣的异步时序逻辑电路设计实例 ——MFM调制模块设计笔记

    本文从本人的163博客搬迁至此. MFM是改进型频率调制的缩写,其本质是一种非归零码,是用于磁介质硬盘存储的一种调制方式.调制规则有两句话,即两个翻转条件: 1.为1的码元在每个码元的正中进行一次翻转 ...

  2. Newtonsoft.Json.Linq对象读取DataSet数据

    Newtonsoft.Json.Linq对象读取DataSet数据: private void button4_Click(object sender, EventArgs e)        {   ...

  3. 20155216 Exp7 网络欺诈技术防范

    Exp7 网络欺诈技术防范 基础问题回答 1.通常在什么场景下容易受到DNS spoof攻击? 1.在同一局域网下比较容易受到DNS spoof攻击,攻击者可以冒充域名服务器,来发送伪造的数据包,从而 ...

  4. # 20155337《网络对抗》Web基础

    20155337<网络对抗>Exp8 Web基础 实践目标 1. 实践内容 (1).Web前端HTML 能正常安装.启停Apache.理解HTML,理解表单,理解GET与POST方法,编写 ...

  5. Tarjan&&缩点简析

    由于昨天写计蒜客初赛的一道题,看出了是缩点,但一时忘记了另外一个叫什么s...的算法怎么写了,话说我为什么没有回去翻一下自己的blog然后今天就去学了更实用也更强力的Tarjan Tarjan的思想其 ...

  6. 使用 idea 的Bookmarks(书签)功能

    https://blog.csdn.net/qq_36376059/article/details/80277767

  7. 01.如何把.py文件打包成为exe,重点讲解pyinstaller的用法

    1.应用场景 1.1 故事背景 我自己用python写了一个小程序发给其他同事用,给他的就是一个.py文件,不过他觉得比较麻烦,还要安装环境,他问我有没有简单一点的方式,我给一个exe文件,他就不用安 ...

  8. kubernetes 集群新增node 节点并将应用分配到新增节点

    第一章 1.重新安装一台kubernetes node节点,新增节点:192.168.1.192 网址:https://www.cnblogs.com/zoulixiang/p/9504324.htm ...

  9. 记录:Ubuntu 18.04 安装 tensorflow-gpu 版本

    狠下心来重新装了系统,探索一下 gpu 版本的安装.比较令人可喜的是,跟着前辈们的经验,还是让我给安装成功了.由于我是新装的系统,就像婴儿般纯净,所以进入系统的第一步就是安装 cuda,只要这个不出错 ...

  10. 初识Redux Middleware

    前言 原先改变store是通过dispatch(action) = > reducer:那Redux的Middleware是什么呢?就是dispatch(action) = > reduc ...