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

Solution

emmm这个题真的有毒啊……INF改成8e8才过……最慢的点跑2s……幸亏BZOJ算总时间
首先看到这个数据范围十有八九网络流没跑了……
先将格子黑白染色,考虑一通操作成功后每个格子的数都是v,若:
1、n*m是奇数。设黑白格子个数为num[0/1],和为sum[0/1],那么$num0*x-sum0=num1*x-sum1$,因为每次操作肯定会给一个黑点和一个白点加。
2、n*m是偶数。如果最终答案是v满足的话,那么显然最终答案是v+1肯定也是可以满足的。这个就可以二分了。
现在的问题转换为判断是否可行。
s-black,容量为v-a[i][j]
white-e,容量为v-a[i][j]
black-white, 容量为INF。
怎么理解呢?把INF边看成给两端的数各自加一,而INF边连着的两端的边又限制了INF边的使用次数。

Code

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define N (2001)
#define INF (8000000000LL)
#define LL long long
using namespace std; struct Edge{LL to,next,flow;}edge[N<<];
LL T,n,m,s,e=,Depth[N],num[],sum[],maxn,cnt;
LL head[N],num_edge,a[N][N],col[N][N],id[N][N];
LL dx[]={,,-,,},dy[]={,,,,-};
queue<LL>q; void add(LL u,LL v,LL l)
{
edge[++num_edge].to=v;
edge[num_edge].next=head[u];
edge[num_edge].flow=l;
head[u]=num_edge;
} LL Dfs(LL x,LL low)
{
if (x==e || low==) return low;
LL f=,Min=;
for (int i=head[x]; i; i=edge[i].next)
if (edge[i].flow && Depth[edge[i].to]==Depth[x]+ && (Min=Dfs(edge[i].to,min(low,edge[i].flow))))
{
edge[i].flow-=Min;
edge[((i-)^)+].flow+=Min;
f+=Min; low-=Min;
if (!low) break;
}
if (!f) Depth[x]=-;
return f;
} bool Bfs(LL s,LL e)
{
memset(Depth,,sizeof(Depth));
Depth[s]=; q.push(s);
while (!q.empty())
{
LL x=q.front(); q.pop();
for (int i=head[x]; i; i=edge[i].next)
if (!Depth[edge[i].to] && edge[i].flow)
{
Depth[edge[i].to]=Depth[x]+;
q.push(edge[i].to);
}
}
return (Depth[e]!=);
} bool Dinic(LL s,LL e)
{
while (Bfs(s,e)) Dfs(s,INF);
for (int i=head[s]; i; i=edge[i].next)
if (edge[i].flow!=) return false;
for (int i=head[e]; i; i=edge[i].next)
if (edge[((i-)^)+].flow!=) return false;
return true;
} bool check(LL v)
{
memset(head,,sizeof(head)); num_edge=;
memset(edge,,sizeof(edge));
for (int i=; i<=n; ++i)
for (int j=; j<=m; ++j)
{
if (col[i][j]) add(s,id[i][j],v-a[i][j]),add(id[i][j],s,);
else add(id[i][j],e,v-a[i][j]),add(e,id[i][j],);
if (!col[i][j]) continue;
for (int k=; k<=; ++k)
{
LL x=i+dx[k], y=j+dy[k];
if (x< || x>n || y< || y>m) continue;
add(id[i][j],id[x][y],INF),add(id[x][y],id[i][j],);
}
}
return Dinic(s,e);
} int main()
{
scanf("%lld",&T);
while (T--)
{
scanf("%lld%lld",&n,&m);
sum[]=sum[]=maxn=cnt=;
if (n*m%) num[]=n*m/+,num[]=n*m/;
else num[]=num[]=n*m/;
for (int i=; i<=n; ++i)
for (int j=; j<=m; ++j)
{
scanf("%lld",&a[i][j]);
id[i][j]=++cnt;
maxn=max(maxn,a[i][j]);
if (i%==j%) col[i][j]=;
sum[col[i][j]]+=a[i][j];
}
if (n*m%)
{
LL v=(sum[]-sum[])/(num[]-num[]);
if (check(v)) printf("%lld\n",(v*n*m-sum[]-sum[])/);
else printf("-1\n");
}
else
{
LL l=maxn, r=INF, ans=-;
while (l<=r)
{
LL mid=(l+r)/;
if (check(mid)) r=mid-,ans=mid;
else l=mid+;
}
if (ans==-) printf("-1\n");
else printf("%lld\n",(ans*n*m-sum[]-sum[])/);
}
}
}

BZOJ2756:[SCOI2012]奇怪的游戏(最大流,二分)的更多相关文章

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

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

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

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

  3. BZOJ2756 [SCOI2012]奇怪的游戏 最大流

    好久没有写博客了.不过这个博客也没有多少人看 最近在写网络流,为了加深理解,来写一两篇题解. 对整个棋盘进行黑白染色以后可以发现,一次操作就是让二分图的两个点的值分别 \(+1\). 这样,我们就可以 ...

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

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

  5. Bzoj2756 [SCOI2012]奇怪的游戏

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

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

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

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

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

  8. BZOJ2756 SCOI2012奇怪的游戏(二分答案+最大流)

    由数据范围容易想到网络流.由于操作只是对于棋盘上相邻两格,容易想到给其黑白染色. 假设已经知道最后要变成什么数.那么给黑白点之间连边,其流量则表示同时增加的次数,再用源汇给其限流为需要增加的数即可. ...

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

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

随机推荐

  1. imx6. android6.0经常修改或者用到的目录(未完)

    系统应用apk存放的文件: out/target/product/sabresd_6dq/system/app 系统配置存放目录:(我自己的,也许不对) out/target/product/sabr ...

  2. [转]Entity FrameWork利用Database.SqlQuery<T>执行存储过程并返回参数

    本文转自:http://www.cnblogs.com/xchit/p/3334782.html 目前,EF对存储过程的支持并不完善.存在以下问题:        EF不支持存储过程返回多表联合查询的 ...

  3. C# WinForm API 改进单实例运行

    在普通的单实例中,第二次点击软件快捷方式的时候,往往简单提示"系统已经运行",而不是把第一次打开的软件主窗体显示出来,下面演示如果主窗体已经打开则把第一次打开的主窗体放置到最前面; ...

  4. jQuery 整体架构

    不同于 jQuery 代码各个模块细节实现的晦涩难懂,jQuery 整体框架的结构十分清晰,按代码行文大致分为如上图所示的模块. 初看 jQuery 源码可能很容易一头雾水,因为 9000 行的代码感 ...

  5. spring mvc如何优雅的使用fastjson

    1. 在spring mvc中配置fastjson <!-- 设置配置方案 --> <mvc:annotation-driven> <!-- 设置不使用默认的消息转换器 ...

  6. Vue-[v-model]理解示例

    对应文档节点: https://vuefe.cn/v2/guide/components.html#Customizing-Component-v-model <body> <div ...

  7. python的爬虫

    requests库的安装 https://blog.csdn.net/xiaokuang5020/article/details/80580631 Response对象属性 属性 说明 r.statu ...

  8. 程序员学炒股(6) 让我们来看一下7月份A股的表现

    有了前几天的数据准备,那让我们看一下7月份的股市是牛市还是熊市呢? 牛市和熊市主要就看股票的涨跌分布情况,虽然我们看大盘数据,但是不过中石油占的A股市值太大了,并且中石油95%的股票都是大股东控制的相 ...

  9. RegExp.prototype.exec()使用技巧

    RegExp.prototype.exec() exec() 方法在一个指定字符串中执行一个搜索匹配.返回一个结果数组或 null. 如果你只是为了判断是否匹配(true或 false),可以使用 R ...

  10. linux 忘记密码

    密码保存在/etc/shadow文件中 1. root 密码忘记了 1.1 重启进入单人维护模式后, 系统会主动给予root权限的bash接口, 此时再以passwd修改密码即可: 1.2 以Live ...