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. php 无限参数方法

    在很多项目开发中经常会用到共用方法但是参数不固定,每个参数都创建一遍阅读性不好,后期维护也麻烦,PHP有获取传入参数的方法,记录参考一下.这里有两个方法 <?php 方法一: #不指定参数个数方 ...

  2. ERROR: bootstrap checks failed

    错误描述:Linux默认配置的参数过小,需要自己设置 max file descriptors [4096] for elasticsearch process is too low, increas ...

  3. 【Hbase一】基础

    此笔记仅用于作者记录复习使用,如有错误地方欢迎留言指正,作者感激不尽,如有转载请指明出处 Hbase基础 Hbase基础 Hbase定义 行存储 v s 列存储 Hbase数据模型 Hbase物理模型 ...

  4. No configuration found for this host:al

    想尝试多个agent来进行传输数据其中的一个配置文件如下: al.sources = r1al.sinks = k1al.channels = c1 al.sources.r1.type = avro ...

  5. django的查询集

    查询集表示从数据库中获取的对象集合,在管理器上调用某些过滤器方法会返回查询集,查询集可以含有零个.一个或多个过滤器.过滤器基于所给的参数限制查询的结果,从Sql的角度,查询集和select语句等价,过 ...

  6. 学习python第一天 pycharm设置

    print(“hello,world”) pycharm设置 1. 选择python 解析器,目的是确定pycharm 的运行环境. 方法: File-->Settings-->Proje ...

  7. A*与IDA*的奇妙之旅

    因为A*卡了一天QAQ 那么,A*是什么呢? A* A*是对于bfs的优化,启发式搜索. 例如下图: 不错,在这张图上,小人去找电脑,用bfs的话: 黄色就是bfs的搜索范围...不要问我为什么选黄色 ...

  8. Linux mysql启动与关闭

    service mysql stop service mysqld start

  9. Kubernetes-Envoy(一种全新的Ingress实现方式)

    Ingress 在讲Envoy之前,先介绍一下Kubernetes中Service的表现形式为IP:Port,及工作在Ingress:TCP/IP层.而对于基于HTTP的服务来说,不同的URL地址经常 ...

  10. 贪心算法之Kruskal

    克鲁斯卡尔Kruskal算法同Prim算法一样,都是求最小生成树.Kruskal是不断的找最短边,加入集合,且不构成回路. 所以,我们可以给每个点定义一个集合,一边的起点和终点查看是否属于同一集合,如 ...