Time Limit: 40 Sec  Memory Limit: 128 MB
Submit: 4403  Solved: 1226
[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

【题解】

         ①你有一个很好的愿望:要是能知道最后的棋盘是什么样子就好了!

         ②设棋盘最后都为x(同时和数与形状相关的问题,染色很实用),

           染色后设白格总数num1,和sum1;黑格总数num2,和sum2;我们可以写下这样的式子:
           x*num1-sum1=x*num2-
sum2 (由于选取相邻的两个格+1) 化一化:
           sum1-sum2=x*(num1-num2) 回到初中学过的一元一次方程解的讨论:
           若num1-num2≠0 ,解出x,若比原图中maxn还小,就一定不行,反之check一下;

           若num1-num2=0,若sum1-sum2≠0肯定就没戏了,反之就此方程对应了很多很多解,考虑实际情况我们可以说在这种情况下:x取a成立的话,取a+1一定成立(但是对a和a-1就不一定对了,我就是错在这里的),二分+check即可;

③check的话就超源连白色,超汇连黑色,边为差值,对白格向相邻黑格建inf边,看是否满流。

 

 /*2
2 2
1 2
2 3
3 3
1 2 3
2 3 4
4 3 2
没去freopen居然调了半个小时,醉了。
inf和INF什么的,最讨厌了。
染色技巧很玄妙!
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <ctime>
#include <cmath>
#define ll long long
#define N 50
#define mem(f,a) memset(f,a,sizeof(f))
#define Run(i,l,r) for(ll i=l;i<=r;i++)
#define Don(i,l,r) for(ll i=l;i>=r;i--)
#define Eun(i,u,E,head) for(ll i=head[u],v=E[i].v;i!=-1;i=E[i].next,v=E[i].v)
using namespace std;
int n,m;
const ll inf=(1LL<<);
const ll INF=(1LL<<);
struct Edge{
int v,next;
ll cap,flow;
}E[];
ll a[N][N],color[N][N];
ll head[N*N],k,cur[N*N],vis[N*N],d[N*N];
int dx[]={,,,-},dy[]={,-,,};
queue<int>q;
int idx(int i,int j){return (i-)*m+j;}
void adde(int u,int v,ll cap)
{ E[k]=(Edge){v,head[u],cap,};
head[u]=k++;
E[k]=(Edge){u,head[v],,};
head[v]=k++;
}
bool Bfs()
{ mem(vis,); mem(d,);
vis[]=; q.push();
while (!q.empty()){
int u=q.front(); q.pop();
Eun(i,u,E,head)if (E[i].cap>E[i].flow&&!vis[v]){
vis[v]=;
q.push(v);
d[v]=d[u]+;
}
}
return (vis[n*m+]);
}
ll Dfs(int u,ll a)
{ if (u==n*m+||a==) return a;
ll flow=,f;
Eun(i,u,E,cur){
cur[u]=i;
if (d[v]==d[u]+&&(f=Dfs(v,min(E[i].cap-E[i].flow,a)))>){
flow+=f;
a-=f;
E[i].flow+=f;
E[i^].flow-=f;
}
if (a==) break;
}
return flow;
}
ll Dinic()
{ ll flow=;
while (Bfs()){
Run(i,,n*m+) cur[i]=head[i];
flow+=Dfs(,INF);
}
return flow;
}
bool check(ll x)
{ k=; mem(head,-);
ll tot=;
Run(i,,n)
Run(j,,m){
if (color[i][j]) {
tot+=x-a[i][j];
adde(,idx(i,j),x-a[i][j]);
Run(k,,){
int ni=i+dx[k]; int nj=j+dy[k];
if (ni>&&nj>&&ni<=n&&nj<=m) adde(idx(i,j),idx(ni,nj),INF);
}
}
else adde(idx(i,j),n*m+,x-a[i][j]);
}
if (tot==Dinic()) return ;
else return ;
}
int main()
{ freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
int T;
scanf("%d",&T);
while (T--){
scanf("%d%d",&n,&m);
ll maxn=,num1=,num2=; ll sum1=,sum2=;
Run(i,,n)
Run(j,,m){
scanf("%lld",&a[i][j]);
maxn=max(maxn,a[i][j]);
if ((i+j)&) color[i][j]=,sum1+=a[i][j],num1++;
else color[i][j]=,sum2+=a[i][j],num2++;
}
if (num1==num2) {
if (sum1!=sum2) {printf("-1\n"); continue;}
ll l=maxn,r=inf,x=;
while (l<r){
ll mid=(l+r)/;
if (check(mid)) x=mid,r=mid;
else l=mid+;
}
if (x) printf("%lld\n",1ll*x*num1-sum1);
else printf("-1\n");
}
else {
ll temp=(sum1-sum2)/(num1-num2);
if (temp>=maxn&&check(temp)) printf("%lld\n",1ll*temp*num1-sum1);
else printf("-1\n");
}
}
return ;
}//by tkys_Austin;

【bzoj2756 奇怪的游戏】的更多相关文章

  1. BZOJ-2756 奇怪的游戏 黑白染色+最大流+当前弧优化+二分判断+分类讨论

    这个题的数据,太卡了,TLE了两晚上,各种调试优化,各种蛋疼. 2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MB Submit ...

  2. [bzoj2756]奇怪的游戏

    对棋盘黑白染色后,若n和m都是奇数(即白色和黑色点数不同),可以直接算得答案(根据白-黑不变):若n和m不都是奇数,二分答案(二分的上限要大一点,开$2^50$),最后都要用用网络流来判定.考虑判定, ...

  3. 【BZOJ2756】奇怪的游戏(二分,最小割)

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

  4. 【BZOJ2756】奇怪的游戏(二分,网络流)

    [BZOJ2756]奇怪的游戏(二分,网络流) 题面 BZOJ Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blink ...

  5. 【BZOJ-2756】奇怪的游戏 最大流 + 分类讨论 + 二分

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

  6. Bzoj2756 [SCOI2012]奇怪的游戏

    2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 3220  Solved: 886 Description ...

  7. BZOJ2756:[SCOI2012]奇怪的游戏(最大流,二分)

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

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

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

  9. bzoj2756: [SCOI2012]奇怪的游戏(网络流+分情况)

    2756: [SCOI2012]奇怪的游戏 题目:传送门 题解: 发现做不出来的大难题一点一个网络流 %大佬 首先黑白染色(原来是套路...)染色之后就可以保证每次操作都一定会使黑白各一个各自的值加1 ...

随机推荐

  1. Hadoop(6)-HDFS的shell操作

    1.基本语法 使用 hadoop fs 具体命令   或者   hdfs dfs 具体命令 hadoop命令的shell源码 hdfs命令的shell源码 由此可见,这两个命令最后都是执行的一个jav ...

  2. 网站漏洞修复之最新版本UEditor漏洞

    UEditor于近日被曝出高危漏洞,包括目前官方UEditor 1.4.3.3 最新版本,都受到此漏洞的影响,ueditor是百度官方技术团队开发的一套前端编辑器,可以上传图片,写文字,支持自定义的h ...

  3. EXKMP学习笔记QAQ

    因为一本通少了一些算法,所以我就自行补充了一些东西上去. EXKMP也就是扩展KMP,是一种特别毒瘤的东西 EXKMP确实很难,我理解他的时间与AC机的时间差不多,而且还很难记,因此一学会就马上写博客 ...

  4. Spring中的设计模式--观察者模式

    spring在容器中使用了观察者模式: 一.spring事件:ApplicationEvent,该抽象类继承了EventObject类,jdk建议所有的事件都应该继承自EventObject. 二.s ...

  5. 【python3.X】python练习笔记[1]

    ##三位数水仙花 ##方法一,小于指定数字的水仙花数 x=eval(input()) a,b,c = 0,0,0 for i in range (100,x,1): a=i%10 b=i//100 c ...

  6. CDH-5.9.2整合spark2

    1.编写目的:由于cdh-5.9.2自带spark版本是spark1.6,现需要测试spark2新特性,需要整合spark2, 且spark1.x和spark2.x可以同时存在于cdh中,无需先删除s ...

  7. Dubbo原理及配置

    技术交流群:233513714 Dubbo的背景 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进 ...

  8. 深度学习:激活函数的比较和优缺点,sigmoid,tanh,relu

    https://blog.csdn.net/u011684265/article/details/78039280

  9. SpringBoot学习:使用logback进行日志记录

    项目下载地址:http://download.csdn.NET/detail/aqsunkai/9805821 (一)pom.xml文件中引入jar: <!-- https://mvnrepos ...

  10. 源码-集合:ArrayList

    只是文章摘录,还未研究 JAVA ArrayList详细介绍(示例) http://www.jb51.net/article/42764.htm Jdk1.6 JUC源码解析汇总 - 永远保持敬畏之心 ...