BZOJ2756 SCOI2012奇怪的游戏(二分答案+最大流)
由数据范围容易想到网络流。由于操作只是对于棋盘上相邻两格,容易想到给其黑白染色。
假设已经知道最后要变成什么数。那么给黑白点之间连边,其流量则表示同时增加的次数,再用源汇给其限流为需要增加的数即可。
考虑最后应该变成什么数。
如果棋盘中黑白格子数量不同,设最后变成的数是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奇怪的游戏(二分答案+最大流)的更多相关文章
- Bzoj2756 [SCOI2012]奇怪的游戏
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3220 Solved: 886 Description ...
- bzoj2756: [SCOI2012]奇怪的游戏(网络流+分情况)
2756: [SCOI2012]奇怪的游戏 题目:传送门 题解: 发现做不出来的大难题一点一个网络流 %大佬 首先黑白染色(原来是套路...)染色之后就可以保证每次操作都一定会使黑白各一个各自的值加1 ...
- bzoj 2756 [SCOI2012]奇怪的游戏 二分+网络流
2756:[SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 4926 Solved: 1362[Submit][Stat ...
- BZOJ2756:[SCOI2012]奇怪的游戏(最大流,二分)
Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻 的格子,并使这两个数都加上 1. 现在 B ...
- BZOJ2756 [SCOI2012]奇怪的游戏 【网络流 + 二分】
题目 Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻 的格子,并使这两个数都加上 1. 现在 Blinker 想知 ...
- P5038 [SCOI2012]奇怪的游戏 二分+网络流
$ \color{#0066ff}{ 题目描述 }$ Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 \(N \times M\) 的棋盘上玩,每个格子有一个数.每次\(Blinker\)会 ...
- BZOJ.2756.[SCOI2012]奇怪的游戏(二分 黑白染色 最大流ISAP)
题目链接 \(Description\) \(Solution\) 这种题当然要黑白染色.. 两种颜色的格子数可能相同,也可能差1.记\(n1/n2\)为黑/白格子数,\(s1/s2\)为黑/白格子权 ...
- BZOJ2756 [SCOI2012]奇怪的游戏 最大流
好久没有写博客了.不过这个博客也没有多少人看 最近在写网络流,为了加深理解,来写一两篇题解. 对整个棋盘进行黑白染色以后可以发现,一次操作就是让二分图的两个点的值分别 \(+1\). 这样,我们就可以 ...
- 洛谷$P5038\ [SCOI2012]$奇怪的游戏 二分+网络流
正解:二分+网络流 解题报告: 传送门$QwQ$ 这种什么,"同时增加",长得就挺网络流的$QwQ$?然后看到问至少加多少次,于是考虑加个二分呗?于是就大体确定了做题方向,用的网络 ...
随机推荐
- 一个有趣的异步时序逻辑电路设计实例 ——MFM调制模块设计笔记
本文从本人的163博客搬迁至此. MFM是改进型频率调制的缩写,其本质是一种非归零码,是用于磁介质硬盘存储的一种调制方式.调制规则有两句话,即两个翻转条件: 1.为1的码元在每个码元的正中进行一次翻转 ...
- Newtonsoft.Json.Linq对象读取DataSet数据
Newtonsoft.Json.Linq对象读取DataSet数据: private void button4_Click(object sender, EventArgs e) { ...
- 20155216 Exp7 网络欺诈技术防范
Exp7 网络欺诈技术防范 基础问题回答 1.通常在什么场景下容易受到DNS spoof攻击? 1.在同一局域网下比较容易受到DNS spoof攻击,攻击者可以冒充域名服务器,来发送伪造的数据包,从而 ...
- # 20155337《网络对抗》Web基础
20155337<网络对抗>Exp8 Web基础 实践目标 1. 实践内容 (1).Web前端HTML 能正常安装.启停Apache.理解HTML,理解表单,理解GET与POST方法,编写 ...
- Tarjan&&缩点简析
由于昨天写计蒜客初赛的一道题,看出了是缩点,但一时忘记了另外一个叫什么s...的算法怎么写了,话说我为什么没有回去翻一下自己的blog然后今天就去学了更实用也更强力的Tarjan Tarjan的思想其 ...
- 使用 idea 的Bookmarks(书签)功能
https://blog.csdn.net/qq_36376059/article/details/80277767
- 01.如何把.py文件打包成为exe,重点讲解pyinstaller的用法
1.应用场景 1.1 故事背景 我自己用python写了一个小程序发给其他同事用,给他的就是一个.py文件,不过他觉得比较麻烦,还要安装环境,他问我有没有简单一点的方式,我给一个exe文件,他就不用安 ...
- kubernetes 集群新增node 节点并将应用分配到新增节点
第一章 1.重新安装一台kubernetes node节点,新增节点:192.168.1.192 网址:https://www.cnblogs.com/zoulixiang/p/9504324.htm ...
- 记录:Ubuntu 18.04 安装 tensorflow-gpu 版本
狠下心来重新装了系统,探索一下 gpu 版本的安装.比较令人可喜的是,跟着前辈们的经验,还是让我给安装成功了.由于我是新装的系统,就像婴儿般纯净,所以进入系统的第一步就是安装 cuda,只要这个不出错 ...
- 初识Redux Middleware
前言 原先改变store是通过dispatch(action) = > reducer:那Redux的Middleware是什么呢?就是dispatch(action) = > reduc ...