P5038 奇怪的游戏
题目询问了一个不能确定的时间,所以显然做法中要包含一个二分答案。
我们将整张图分为黑白点两种,黑点旁边的点就是白点,白点旁边的点就是黑点,想一下就能知道,每次操作会使黑白点的数字各加一,而我们的目的就是让整张图的黑白点都是同一个数字。
设这个数字是 \(x\),黑点有 \(num_0\) 个,未操作前的数字总和是 \(sum_0\),白点有 \(num_1\) 个,未操作前的数字总和是 \(sum_1\),因为操作次数相等,
那么有:
\]
移项可得:
\]
于是:
当 \(num_1 \not= num_0\) 时,可以解出 \(x\),若它是个小数则无解。另外我们要操作的次数为 \((x\times n\times m-sum_1-sum_0)/2\) ,所以如果这也是一个小数也无解,接着我们用网络流 \(check\) 一下 \(x\),得出它能操作多少次,和上面算的一样就有解,否则无解。
\(num_1=num_0\) 显然这说明 \(n,m\) 中至少一个是偶数,操作次数还是 \((x\times n\times m-sum_1-sum_0)/2\),前一项是偶数,后两项算一下如果是奇数,那么算出次数一定是小数,也无解,否则我们就可以利用单调性二分出合适的 \(x\) ,利用网络流得出答案。
单调性证明:
因为 \(num_1=num_0\), 则
\]
即可以构造一层正好的满覆盖。也就是在正确答案后多铺了几层。所以具有单调性。
于是本题就愉快的做完了~
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define int long long
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int N=1650;struct dp{int num,sum;}p[2];const int inf1=1e18,inf2=1e14;
int head[N],dis[N],co,Hd[N],n,pos[45][45],q[N],hd,tot,tl,cnt,m,S,T,a[45][45],b[45][45];struct node{int next,to,w;}e[N*10];
inline void add(int next,int to,int w){e[++co].next=head[next],e[co].to=to,e[co].w=w,head[next]=co;}
inline bool bfs(){
memcpy(head,Hd,sizeof(Hd));
memset(dis,0x3f,sizeof(dis));
q[hd=tl=1]=S;dis[S]=0;
while(hd<=tl){
int x=q[hd++];
for(register int i=head[x];i;i=e[i].next)if(e[i].w){
if(dis[e[i].to]>dis[x]+1){
dis[e[i].to]=dis[x]+1;
q[++tl]=e[i].to;
}
}if(x==T)return 1;
}return 0;
}
inline int dfs(int x,int in){
if(x==T)return in;
int rest=in,go;
for(register int i=head[x];i;head[x]=i=e[i].next)if(e[i].w){
if(dis[e[i].to]==dis[x]+1){
go=dfs(e[i].to,min(e[i].w,rest));
if(go)e[i].w-=go,e[i^1].w+=go,rest-=go;
else dis[e[i].to]=0;
}if(!rest)break;
}return in-rest;
}
inline int check(int x){
int ans=0;co=1;
memset(head,0,sizeof(head));tot=x*n*m-p[0].sum-p[1].sum;
F(i,1,n)
F(j,1,m)
if(b[i][j]){
if(j+1<=m)add(pos[i][j],pos[i][j+1],inf1),add(pos[i][j+1],pos[i][j],0);
if(j-1>=1)add(pos[i][j],pos[i][j-1],inf1),add(pos[i][j-1],pos[i][j],0);
if(i-1>=1)add(pos[i][j],pos[i-1][j],inf1),add(pos[i-1][j],pos[i][j],0);
if(i+1<=n)add(pos[i][j],pos[i+1][j],inf1),add(pos[i+1][j],pos[i][j],0);
add(S,pos[i][j],x-a[i][j]);add(pos[i][j],S,0);
}else add(pos[i][j],T,x-a[i][j]),add(T,pos[i][j],0);
memcpy(Hd,head,sizeof(head));
while(bfs())ans+=dfs(S,inf1);
if(ans>=tot/2)return ans;else return 0;
}
inline short main(){
int TT=read();
while(TT--){
cnt=0;n=read(),m=read();S=++cnt;T=++cnt;int maxn=0;
p[0].num=p[0].sum=p[1].num=p[1].sum=0;
F(i,1,n)
F(j,1,m){
if(j==1)b[i][j]=b[i-1][j]^1;else b[i][j]=b[i][j-1]^1;
p[b[i][j]].num++;pos[i][j]=++cnt;
a[i][j]=read();p[b[i][j]].sum+=a[i][j];
maxn=max(maxn,a[i][j]);
}
if(p[1].num!=p[0].num){
if((p[1].sum-p[0].sum)%(p[1].num-p[0].num)!=0){pi(-1);pn();}
int tt=(p[1].sum-p[0].sum)/(p[1].num-p[0].num);
int x;
if(tt!=(int)tt){pi(-1);pn();continue;}else x=tt;
if((x*n*m-p[1].sum-p[0].sum)&1||x*n*m<p[1].sum+p[0].sum){pi(-1);pn();continue;}
if(!check(x)){pi(-1);pn();}
else{pi(check(x));pn();}
}else{
int l=maxn,r=inf2,ans=inf2;
if((p[0].sum+p[1].sum)&1){pi(-1);continue;}
while(l<=r){
int mid=(l+r)>>1;
int t=check(mid);
if(t)r=mid-1,ans=t;
else l=mid+1;
}
if(ans==inf2){pi(-1);pn();continue;}
else pi(ans),pn();
}
}
return 0;
}
}
signed main(){return EMT::main();}
P5038 奇怪的游戏的更多相关文章
- [题目] Luogu P5038 [SCOI2012]奇怪的游戏
学习资料 -----1----- -----2----- P5038 [SCOI2012]奇怪的游戏 一道甚神但没用到高深模型的题 思路 没思路,看题解吧 代码 #include <iostre ...
- P5038 [SCOI2012]奇怪的游戏 二分+网络流
$ \color{#0066ff}{ 题目描述 }$ Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 \(N \times M\) 的棋盘上玩,每个格子有一个数.每次\(Blinker\)会 ...
- BZOJ 2756: [SCOI2012]奇怪的游戏 [最大流 二分]
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3352 Solved: 919[Submit][Stat ...
- bzoj 2756奇怪的游戏
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MB Description Blinke 最近喜欢上一个奇怪的游戏. 这个游戏 ...
- 【BZOJ-2756】奇怪的游戏 最大流 + 分类讨论 + 二分
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 2925 Solved: 792[Submit][Stat ...
- Bzoj2756 [SCOI2012]奇怪的游戏
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3220 Solved: 886 Description ...
- 【BZOJ2756】奇怪的游戏(二分,最小割)
题意: Blinker最近喜欢上一个奇怪的游戏.这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻的格子,并使这两个数都加上 1.现在 Blinker 想知道最 ...
- BZOJ-2756 奇怪的游戏 黑白染色+最大流+当前弧优化+二分判断+分类讨论
这个题的数据,太卡了,TLE了两晚上,各种调试优化,各种蛋疼. 2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MB Submit ...
- 【BZOJ】【2756】【SCOI2012】奇怪的游戏
网络流-最大流 这题……建模部分先略过 这道题是会卡时限的T_T俺的Dinic被卡了,在此放几篇很棒的讲网络流算法的文章,至于大家耳熟能详的论文就不放了…… http://www.cppblog.co ...
随机推荐
- 你知道购买车票的原理吗?Java 线程同步
先看再点赞,给自己一点思考的时间,如果对自己有帮助,微信搜索[程序职场]关注这个执着的职场程序员.我有什么:职场规划指导,技能提升方法,讲不完的职场故事,个人成长经验. 大周末的还是6点起床,起床的第 ...
- 打开设置windows10内置linux功能-启用linux子系统
第一步设置开发者模式 步骤:windows+s打开娜娜,输入设置,并点击. 点击更新与安全 点击开发者选项,选择开发者模型,弹出的对话框选确定之后等待安装完毕. 第二步:安装linux 点击确定后等待 ...
- WPF教程十一:简单了解并使用控件模板
WPF教程十一:简单了解并使用控件模板 这一章梳理控件模板,每个WPF控件都设计成无外观的,但是行为设计上是不允许改变的,比如使用Button的控件时,按钮提供了能被点击的内容,那么自由的改变控件外观 ...
- WPF教程一:创建Hello world来理解XAML的内容及编译
在实际的WPF开发中遇到很多再用Winform写法来写WPF的开发人员,很多时候项目进度延期.出现非必要的BUG等等.大多是因为开发人员虽然是再写WPF. 但是没有好好的学过WPF,就导致无法发挥出W ...
- Dart学习记录(一)——对象
1. 静态成员.方法 1.1 static 声明 1.2 静态.非静态方法可访问静态成员.调用方法:静态方法不可访问静态成员.调用方法: 1.3 静态成员.方法,属于类的 ,不用实例化对象就可使用,不 ...
- 获取操作系统OS等相关信息
问题一:Windows SDK 8.1版本中的VersionHelper.h文件当中没有IsWindows10ORGreater,所以当你用IsWindows8Point1ORGreater判断出版本 ...
- 高校表白App-团队冲刺第一天
今天要做什么 今天要再次重新的好好学一下Activity的生命周期,简单的写一个Activity,熟悉Activity的线程. 遇到的问题 在点击事件发生时,在activity进行finish()后, ...
- java 实现中英文拼写检查和错误纠正?可我只会写 CRUD 啊!
简单的需求 临近下班,小明忙完了今天的任务,正准备下班回家. 一条消息闪烁了起来. "最近发现公众号的拼写检查功能不错,帮助用户发现错别字,体验不错.给我们系统也做一个." 看着这 ...
- 一:Vue项目构建
第一步:需要安装nodeJS的环境,直接去官网下载https://nodejs.org/en/,下载下来按照提示一步步的安装.(vue.js是一个Js 框架.在node里面通过Npm 安装,是为了方便 ...
- python基础之列表推导式
#列表推导式 ---> 返回的是列表 for语句 效率更高# 1*1 2*2 3*3 4*4 5*5 6*6 7*7 8*8 9*9# import time# to = time.clock( ...