达成成就:为二分调参

!:多次memset的话要把数组大小开严格一点,否则会T

看到网格图,首先黑白染色。

注意到每次操作都是在一个黑格子和一个白格子上进行的,也就是说,最后黑格子数字和白格子数字和的差是不变的。

对于n*m%2==0的情况:

  • 注意到在这种情况下黑格子和白格子一样多,也就是当黑格子数字和和白格子数字和不相等时,一定是不合法状态,反之一定合法。
  • 那么二分最小的最终数字

对于于n*m%2==1情况:

  • 注意到在这种情况下两种格子的数量差1,也就是说格子个数较多的一种格子的数字和与另一种格子的数字和之差就是最终数字。不合法状态之一即为数字之差比初始状态中数字最大的格子中的数字小。
  • 那么判断是否合法

判断方法:

  • 建立流量网络,s连向所有黑格子,所有白格子连向t,流量均为当前格子的值与最终数字之差,所有黑格子向与他相邻的白格子连流量为inf的边(黑白格子反过来也可以)
  • 跑最大流,看是否全部满流,即可以通过一些方案使所有格子达到最终数字
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const long long N=55,P=25005,inf=1e11;
long long T,n,m,a[N][N],col[N][N],sum,le[P],cnt,h[P],s,t,mn,c0,c1,s0,s1;
struct qwe
{
long long ne,to,va;
}e[P<<1];
long long read()
{
long long r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
void add(long long u,long long v,long long w)
{
cnt++;
e[cnt].ne=h[u];
e[cnt].to=v;
e[cnt].va=w;
h[u]=cnt;
}
void ins(long long u,long long v,long long w)
{// cout<<u<<" "<<v<<" "<<w<<endl;
add(u,v,w);
add(v,u,0);
}
bool bfs()
{
memset(le,0,sizeof(le));
queue<long long>q;
le[s]=1;
q.push(s);
while(!q.empty())
{
long long u=q.front();
q.pop();
for(int i=h[u];i;i=e[i].ne)
if(e[i].va>0&&!le[e[i].to])
{
le[e[i].to]=le[u]+1;
q.push(e[i].to);
}
}
return le[t];
}
long long dfs(long long u,long long f)
{
if(u==t||!f)
return f;
long long us=0;
for(int i=h[u];i&&us<f;i=e[i].ne)
if(e[i].va>0&&le[e[i].to]==le[u]+1)
{
long long t=dfs(e[i].to,min(e[i].va,f-us));
e[i].va-=t;
e[i^1].va+=t;
us+=t;
}
if(!us)
le[u]=0;
return us;
}
long long dinic()
{
long long re=0;
while(bfs())
re+=dfs(s,inf);
return re;
}
bool ok(long long c)
{
memset(h,0,sizeof(h));
long long sum=0ll;
cnt=1;s=0,t=n*m+1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
long long x=(i-1)*m+j;
if(col[i][j])
{
ins(s,x,c-a[i][j]),sum+=c-a[i][j];
if(i!=1)
ins(x,(i-2)*m+j,inf);
if(i!=n)
ins(x,i*m+j,inf);
if(j!=1)
ins(x,(i-1)*m+j-1,inf);
if(j!=m)
ins(x,(i-1)*m+j+1,inf);
}
else
ins(x,t,c-a[i][j]);
}
return dinic()==sum;
}
int main()
{
T=read();
while(T--)
{
c0=c1=s0=s1=mn=0;
n=read(),m=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
a[i][j]=read();
col[i][j]=(i+j)&1;
mn=max(mn,a[i][j]);
if(col[i][j])
s1+=a[i][j],c1++;
else
s0+=a[i][j],c0++;
}
if(c0!=c1)
{
long long x=(s0-s1)/1;
if(x>mn&&ok(x))
printf("%lld\n",x*c1-s1);
else
puts("-1");
}
else
{
if(s0!=s1)
{
puts("-1");
continue;
}
long long l=mn,r=inf;
while(l<=r)
{
long long mid=(l+r)>>1;
if(ok(mid))
r=mid-1;
else
l=mid+1;
}
printf("%lld\n",l*c1-s1);
}
}
return 0;
}

bzoj 2756 [SCOI2012]奇怪的游戏【二分+最大流】的更多相关文章

  1. bzoj 2756 [SCOI2012]奇怪的游戏 二分+网络流

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

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

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

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

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

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

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

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

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

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

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

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

    这道题提醒我,要有将棋盘黑白染色的意识,尤其是看到相邻格子这样的条件的时候,然后就是要用到与其有关的性质与特点以体现其作用,这道题就是用到了黑格子与白格子之间的关系进行的,其出发点是每次一定会给一个黑 ...

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

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

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

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

随机推荐

  1. poj1308+HOJ1325,判断是否为树

    POJ 应该是判断是否为简单无环连通图,用并查集直接秒杀即可,而HOJ的是有向树,还需判断所有点的入度必需小于2,用一个类似hash[]数组判断一下即可, ////判断树之一:入度<=1:三:点 ...

  2. com.sun.xxx.utils不存在问题的解决

    com.sun.org.apache.xml.internal.security.utils does not exist问题的解决 在网上找个很多的答案,但我的问题没有解决,睡一晚上后,被我误打误撞 ...

  3. SpringMvc架构流程

  4. 操作redis有关的命令

    )连接操作命令 quit:关闭连接(connection) auth:简单密码认证 help cmd: 查看cmd帮助,例如:help quit )持久化 save:将数据同步保存到磁盘 bgsave ...

  5. Office EXCEL 创建图片超链接打不开怎么办 Excel打开图片提示发生了意外错误怎么办

    如下图所示,点击超链接提示无法打开指定的文件   如果使用Office打开,则提示发生了意外错误   你需要先把IE浏览器打开,这样就可以打开了,并非是图像的相对位置不正确导致的.      

  6. Please enter a commit message to explain why this merge is necessary.

    Please enter a commit message to explain why this merge is necessary. 请输入提交消息来解释为什么这种合并是必要的 git 在pul ...

  7. random模块的使用

    random模块用于生成随机数 import random print random.random() #用于生成小于1大于0的数 print random.randint(1,5) #生成大于等于1 ...

  8. 《coredump问题原理探究》Linux x86版7.9节list相关的iterator对象

    这一节.看一下list的iterator对象在内存的布局 1 #include <list> 2 3 void init( std::list<int>& lst ) ...

  9. 3.2.1 配置构建Angular应用——简单的笔记存储应用——编辑功能

    本节我们会接着上节课的内容,继续来完成使用Angular来创建简单的笔记存储应用,上一节课,我们完成了笔记的展示功能,本节课,我们来完成编辑功能. 编辑主要是两个功能:编辑现有的笔记以及创建新笔记.首 ...

  10. Axure使用笔记

    软件设置类 两个矩形的双边框,边框重合: 项目---项目设置---边界对齐---内边界对齐. 自动备份时间设置 文件-自动备份设置-默认15分钟,根据电脑硬件可以调整. Axure 8 可以不用安装 ...