bzoj 2756 [SCOI2012]奇怪的游戏 二分+网络流
2756:[SCOI2012]奇怪的游戏
Time Limit: 40 Sec Memory Limit: 128 MB
Submit: 4926 Solved: 1362
[Submit][Status][Discuss]
Description
Blinker最近喜欢上一个奇怪的游戏。
这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数。每次 Blinker 会选择两个相邻
的格子,并使这两个数都加上 1。
现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成同
一个数则输出-1。
Input
输入的第一行是一个整数T,表示输入数据有T轮游戏组成。
每轮游戏的第一行有两个整数N和M, 分别代表棋盘的行数和列数。
接下来有N行,每行 M个数。
Output
对于每个游戏输出最少能使游戏结束的次数,如果永远不能变成同一个数则输出-1。
Sample Input
2 2
1 2
2 3
3 3
1 2 3
2 3 4
4 3 2
Sample Output
-1
HINT
【数据范围】
对于30%的数据,保证 T<=10,1<=N,M<=8
对于100%的数据,保证 T<=10,1<=N,M<=40,所有数为正整数且小于1000000000
Source
对棋盘进行黑白染色
设黑格个数为num1 数值和为sum1
设白格个数为num1 数值和为sum1
设最后都变为x
则
num1 * x – sum1 = num2 * x – sum2
x = (sum1 – sum2) / (num1 – num2)
当num1 ≠ num2时 可以解出 x 再用网络流check即可
对于num1 = num2时 可以发现 对于一个合法的x k>=x都是一个合法的解
因为num1 = num2 => (num1 + num2) % 2 == 0 可以构造一层的满覆盖
所以可以二分x 然后用网络流check
建图:
如果点k为白
建边(s, k, x – v[k])
如果为黑
建边(k, t, x – v[k])
对相邻点u、v (u为白)
建边 (u, v, inf)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath> #define inf (1LL<<50)
#define pa pair<int,int>
#define ll long long
#define p(x,y) (x-1)*m+y
using namespace std;
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} ll s0,s1;
int c0,c1;
int test,n,m,cnt,S,T;
int xx[]={,,,-},yy[]={,-,,};
int a[][];
int last[],h[],q[],cur[];
bool color[][];
struct edge{
int to,next;ll v;
}e[]; void insert(int u,int v,ll w)
{
e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].v=w;
e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;e[cnt].v=;
}
bool bfs()
{
int head=,tail=;
memset(h,-,sizeof(h));
q[]=S;h[S]=;
while(head!=tail)
{
int now=q[head];head++;
for(int i=last[now];i;i=e[i].next)
if(e[i].v&&h[e[i].to]==-)
{
h[e[i].to]=h[now]+;
q[tail++]=e[i].to;
}
}
return h[T]!=-;
}
ll dfs(int x,ll f)
{
if(x==T)return f;
ll w,used=;
for(int i=cur[x];i;i=e[i].next)
if(h[e[i].to]==h[x]+)
{
w=dfs(e[i].to,min(f-used,e[i].v));
e[i].v-=w;e[i^].v+=w;
if(e[i].v)cur[x]=i;
used+=w;if(used==f)return f;
}
if(!used)h[x]=-;
return used;
}
ll dinic()
{
ll tmp=;
while(bfs())
{
for(int i=S;i<=T;i++)cur[i]=last[i];
tmp+=dfs(S,inf);
}
return tmp;
}
bool check(ll x)
{
memset(last,,sizeof(last));
cnt=;S=;T=n*m+;
ll tot=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(color[i][j])
{
insert(S,p(i,j),x-a[i][j]);tot+=x-a[i][j];
for(int k=;k<;k++)
{
int nowx=i+xx[k],nowy=j+yy[k];
if(nowx<||nowy<||nowx>n||nowy>m)continue;
insert(p(i,j),p(nowx,nowy),inf);
}
}
else insert(p(i,j),T,x-a[i][j]);
if(dinic()==tot)return ;
return ;
}
int main()
{
test=read();
while(test--)
{
c0=c1=s0=s1=;
n=read();m=read();
int mx=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
a[i][j]=read(),color[i][j]=(i+j)&;
mx=max(mx,a[i][j]);
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(color[i][j])s1+=a[i][j],c1++;
else s0+=a[i][j],c0++;
if(c0!=c1)
{
ll x=(s0-s1)/(c0-c1);
if(x>=mx)
if(check(x))
{
printf("%lld\n",x*c1-s1);
continue;
}
puts("-1");
}
else
{
if(s0!=s1)
{
puts("-1");
continue;
}
ll l=mx,r=inf;
while(l<=r)
{
ll mid=(l+r)>>;
if(check(mid))r=mid-;
else l=mid+;
}
printf("%lld\n",(ll)l*c1-s1);
}
}
}
bzoj 2756 [SCOI2012]奇怪的游戏 二分+网络流的更多相关文章
- BZOJ.2756.[SCOI2012]奇怪的游戏(二分 黑白染色 最大流ISAP)
题目链接 \(Description\) \(Solution\) 这种题当然要黑白染色.. 两种颜色的格子数可能相同,也可能差1.记\(n1/n2\)为黑/白格子数,\(s1/s2\)为黑/白格子权 ...
- BZOJ 2756: [SCOI2012]奇怪的游戏 网络流/二分
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 1594 Solved: 396[Submit][Stat ...
- BZOJ 2756: [SCOI2012]奇怪的游戏 [最大流 二分]
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3352 Solved: 919[Submit][Stat ...
- bzoj 2756: [SCOI2012]奇怪的游戏
Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻 的格子,并使这两个数都加上 1. 现在 B ...
- P5038 [SCOI2012]奇怪的游戏 二分+网络流
$ \color{#0066ff}{ 题目描述 }$ Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 \(N \times M\) 的棋盘上玩,每个格子有一个数.每次\(Blinker\)会 ...
- BZOJ 2756 SCOI2012 奇怪的游戏 最大流
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2756 Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N ...
- 洛谷$P5038\ [SCOI2012]$奇怪的游戏 二分+网络流
正解:二分+网络流 解题报告: 传送门$QwQ$ 这种什么,"同时增加",长得就挺网络流的$QwQ$?然后看到问至少加多少次,于是考虑加个二分呗?于是就大体确定了做题方向,用的网络 ...
- bzoj 2756 [SCOI2012]奇怪的游戏【二分+最大流】
达成成就:为二分调参 !:多次memset的话要把数组大小开严格一点,否则会T 看到网格图,首先黑白染色. 注意到每次操作都是在一个黑格子和一个白格子上进行的,也就是说,最后黑格子数字和白格子数字和的 ...
- BZOJ2756 [SCOI2012]奇怪的游戏 【网络流 + 二分】
题目 Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻 的格子,并使这两个数都加上 1. 现在 Blinker 想知 ...
随机推荐
- 关于JUnit4无法支持多线程测试的解决方法
转自:https://segmentfault.com/a/1190000003762719 其实junit是将test作为参数传递给了TestRunner的main函数.并通过main函数进行执行. ...
- js分类多选全选
效果如图: HTML代码: <div class="form-group quanxian-wrap"> <label>项目</label> & ...
- ora-12154 TNS:"无法处理服务名"的一个解决方法
http://www.cnblogs.com/xh3/archive/2007/04/21/722217.html 很怪异的一个问题,在网络环境下配置客户端,竟然怎么也连不上主机了,看了不少帖子,大多 ...
- 给apk签名
一.签名 把apk和签名文件放在jdk bin目录下,然后在jkd bin目录下执行以下代码: jarsigner -verbose -keystore xxx.keystore -signedjar ...
- 【Java】Map转换器
描述: 在控制层接收参数时候, 往往会出现Json格式需要转换为Bean. 通常一两个字段可以用new去save pojo, 但字段多的情况呢? 以下就是为了解决这个尴尬情况, 自己写一个转换工具类 ...
- Laxcus大数据管理系统2.0 (1) - 摘要和目录
Laxcus大数据管理系统 (version 2.0) Laxcus大数据实验室 摘要 Laxcus是Laxcus大数据实验室全体系全功能设计研发的多用户多集群大数据管理系统,支持一到百万台级节点,提 ...
- lintcode-91-最小调整代价
91-最小调整代价 给一个整数数组,调整每个数的大小,使得相邻的两个数的差不大于一个给定的整数target,调整每个数的代价为调整前后的差的绝对值,求调整代价之和最小是多少. 注意事项 你可以假设数组 ...
- 【linux】linux中tree的安装
# 2018/7/29 10:17:46测试成功! 一 Tree命令简介 tree是一种递归目录列表命令,产生一个深度缩进列表文件. 二 Tree命令安装 1.下载安装包,地址:http://mama ...
- Flink之状态之状态获取
1.什么是状态 对于任何一个操作,都可以被看成是一个函数,比如y=f(x),如果对于同一个x的任何一次输入,得到的y都是相同的,则可以认为这个函数是无状态,否则,这个函数就是有状态的.Flink的一大 ...
- React & styled component
React & styled component https://www.styled-components.com/#your-first-styled-component tagged t ...