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 2
1 2
2 3
3 3
1 2 3
2 3 4
4 3 2

Sample Output

2
-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]奇怪的游戏 二分+网络流的更多相关文章

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

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

  2. BZOJ 2756: [SCOI2012]奇怪的游戏 网络流/二分

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

  3. BZOJ 2756: [SCOI2012]奇怪的游戏 [最大流 二分]

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

  4. bzoj 2756: [SCOI2012]奇怪的游戏

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

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

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

  6. BZOJ 2756 SCOI2012 奇怪的游戏 最大流

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2756 Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N ...

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

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

  8. bzoj 2756 [SCOI2012]奇怪的游戏【二分+最大流】

    达成成就:为二分调参 !:多次memset的话要把数组大小开严格一点,否则会T 看到网格图,首先黑白染色. 注意到每次操作都是在一个黑格子和一个白格子上进行的,也就是说,最后黑格子数字和白格子数字和的 ...

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

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

随机推荐

  1. (数据科学学习手札33)基于Python的网络数据采集实战(1)

    一.简介 前面两篇文章我们围绕利用Python进行网络数据采集铺垫了很多内容,但光说不练是不行的,于是乎,本篇就将基于笔者最近的一项数据需求进行一次网络数据采集的实战: 二.网易财经股票数据爬虫实战 ...

  2. java 堆栈内存分析详解

    计算机术语里面堆和栈代表不同的存储结构:stack-栈:heap-堆 所以java虚拟机(JVM)中堆和栈是两种内存 堆.栈对比 对比点 堆 栈 JVM中的功能 内存数据区 内存指令区 动静态 运行时 ...

  3. bootstrap重新设计checkbox样式

    文章采集于: https://www.cnblogs.com/GumpYan/p/7845445.html#undefined 在原文基础上修改了勾勾的内容,直接采用bootstrap字体库.修改了横 ...

  4. php用GD库给图片添加水印

    php用GD库给图片添加文字水印,整个代码比较简单,DEMO如下: <?php /*打开图片*/ //1.配置图片路径 $src = "aeroplane.jpg"; //2 ...

  5. css的水平居中和垂直居中总结

    Html代码: <div class="md-warp"> <div class="md-main">块级元素</div> ...

  6. linux学习笔记---学习总结②

    table ----> 展示数据 table --->表格 border cellspacing cellpadding width height tr --->行 align th ...

  7. kaldi常用文件查看指令

    目录 1. ark特征文件 2. FST文件 3. mdl模型文件 4. 决策树文件 5. ali.gz对齐文件 资料来自kaldi官方文档. 转载注明出处. 1. ark特征文件 copy-feat ...

  8. 简易cmake多文件多目录工程模板

    今天心血来潮,想在服务器上试试写libevent的工程是什么感受,那第一步就是学会怎么用cmake建工程,之前也没接触过cmake,然后一上午,比较懵逼,下午看实验室哥们给的一个教程,然后,慢慢理解C ...

  9. UVA 11884 A Shooting Game(记忆化搜索)

    A and B are playing a shooting game on a battlefield consisting of square-shaped unit blocks. The bl ...

  10. iOS-缓存

    1. 实现数据模型缓存 可以用NSKeyedArchiver类来实现数据模型缓存.为了把模型对象用NSKeyedArchiver归档,模型类需要遵循NSCoding协议. . 应该用哪种缓存技术 在众 ...