BZOJ 2756: [SCOI2012]奇怪的游戏 网络流/二分
2756: [SCOI2012]奇怪的游戏
Time Limit: 40 Sec Memory Limit: 128 MB
Submit: 1594 Solved: 396
[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
题解:
我们把整个棋盘的格子分为两种,一种为白,一种为黑
然后设最后的格子全部变成了x,那么x*num1-sum1=x*num2-sum2;
其中num1为白色格子数量,num2位黑色格子数量,sum1为白色格子权值和
那么,我们可以得到x=(sum1-sum2)/(num1-num2)
当num1!=num2的时候,我们可以直接通过最大流来check
否则的话,我们就二分枚举答案
首先如果x能够成立的话,那么大与x的所有数都能成立,只要再铺一层就好,而且num1+num2%2==0
所以题目的思路还是比较简单的~
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<set>
#include<ctime>
#include<vector>
#include<queue>
#include<algorithm>
#include<map>
#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
{
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);
}
}
return ;
}
BZOJ 2756: [SCOI2012]奇怪的游戏 网络流/二分的更多相关文章
- bzoj 2756 [SCOI2012]奇怪的游戏【二分+最大流】
达成成就:为二分调参 !:多次memset的话要把数组大小开严格一点,否则会T 看到网格图,首先黑白染色. 注意到每次操作都是在一个黑格子和一个白格子上进行的,也就是说,最后黑格子数字和白格子数字和的 ...
- BZOJ 2756: [SCOI2012]奇怪的游戏 [最大流 二分]
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3352 Solved: 919[Submit][Stat ...
- bzoj 2756 [SCOI2012]奇怪的游戏 二分+网络流
2756:[SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 4926 Solved: 1362[Submit][Stat ...
- bzoj 2756: [SCOI2012]奇怪的游戏
Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻 的格子,并使这两个数都加上 1. 现在 B ...
- BZOJ 2756 SCOI2012 奇怪的游戏 最大流
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2756 Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N ...
- BZOJ.2756.[SCOI2012]奇怪的游戏(二分 黑白染色 最大流ISAP)
题目链接 \(Description\) \(Solution\) 这种题当然要黑白染色.. 两种颜色的格子数可能相同,也可能差1.记\(n1/n2\)为黑/白格子数,\(s1/s2\)为黑/白格子权 ...
- bzoj2756: [SCOI2012]奇怪的游戏(网络流+分情况)
2756: [SCOI2012]奇怪的游戏 题目:传送门 题解: 发现做不出来的大难题一点一个网络流 %大佬 首先黑白染色(原来是套路...)染色之后就可以保证每次操作都一定会使黑白各一个各自的值加1 ...
- 洛谷5038 [SCOI2012]奇怪的游戏(二分+网络流+判断奇偶)
寒假的时候就听过这个题.但是一直没有写. qwq 首先,我们发现题目中的图是个网格图,然后每次可以将相邻两个格子加一. 很容易就想到是黑白染色.那么每次操作,就相当于同时操作一个白点,一个黑点. 我们 ...
- BZOJ2756 SCOI2012奇怪的游戏(二分答案+最大流)
由数据范围容易想到网络流.由于操作只是对于棋盘上相邻两格,容易想到给其黑白染色. 假设已经知道最后要变成什么数.那么给黑白点之间连边,其流量则表示同时增加的次数,再用源汇给其限流为需要增加的数即可. ...
随机推荐
- MySQL服务器修改主机名后问题解决
1.单机MySQL主机名修改 今天无事看到自己的主机名不对,于是改了一下,以便区分服务器,那只重启MySQL时出现下面错误: MySQL manager or server PID file coul ...
- 虚拟环境pipenv的使用
安装虚拟环境 安装python3.6 python -m site --user-base 找到 用户基础目录 指定python版本的方式 pipenv --python 3.8 安装 用户范围内安装 ...
- re-sign重签名
准备: ① re-sign.jar重签名工具:(下载地址为:http://troido.de/downloads/category/1): ② 从D:\Android\sdk\build-tools\ ...
- scrapy shell命令的【选项】简介
在使用scrapy shell测试某网站时,其返回400 Bad Request,那么,更改User-Agent请求头信息再试. DEBUG: Crawled () <GET https://w ...
- pyquery学习笔记
很早就听说了pyquery的强大.写了个简单的测试程序实验下. 思路是找个动态网页,先用PhantomJS加载,然后用PYQUERY解析. 1.随便找了个带表格的股票网页,里面有大量的股票数据,测试的 ...
- java 多线程总结篇3之——生命周期和线程同步
一.生命周期 线程的生命周期全在一张图中,理解此图是基本: 线程状态图 一.新建和就绪状态 当程序使用new关键字创建了一个线程之后,该线程就处于新建状态,此时它和其他的Java对象一样,仅仅由Jav ...
- 记一次对 Laravel-permission 项目的性能优化
我最近研究分析了在 SWIS上面创建的项目的性能.令人惊讶的是,最耗费性能的方法之一是优秀的 spatie/laravel-permission 包造成的. 经过查阅更多资料和研究,发现一个可能明显 ...
- Centos之链接命令
链接命令:ln (link) ln -s [源文件] [目标文件] 功能描述:生成链接文件 选项: -s 创建软链接 硬链接特征: 1,拥有相同的i节点和存储block块,可以看作是同一个文件: 2 ...
- TeamViewer的下载地址,低调低调
https://github.com/cary-zhou/TeamViewer13-Crack
- C++拾遗——重新开始
http://www.cnblogs.com/uniqueliu/category/307731.html