bzoj2756: [SCOI2012]奇怪的游戏(网络流+分情况)
2756: [SCOI2012]奇怪的游戏
题目:传送门
题解:
发现做不出来的大难题一点一个网络流
%大佬
首先黑白染色(原来是套路...)染色之后就可以保证每次操作都一定会使黑白各一个各自的值加1
那么我们接着统计一下黑白格子个数cnt1和cnt2,以及各自的权值和sum1和sum2
然后就要分情况讨论了:
1、在cnt1不等于cnt2的情况下
假设有解且最终的数值均为ans,那么不难发现:cnt1*ans-cnt2*ans=sum1-sum2(因为每次操作黑白格子的总和同时加1,所以总和差始终不变)
那就可以直接推导出ans=(sum1-sum2)/(cnt1-cnt2) 那么我们其实就只需要判断一下该值是否合法就OK
2、cnt1=cnt2
若sum1不等于sum2 那么一定输出-1,因为差不变啊,显然(不过好像没有这种点)
若sum1=sum2,那么设最终的数值为ans
如果ans满足答案,那么ans+1也一定满足,显然存在单调性,直接就二分check
判断ans是否合法:st连白点,流量ans-d[i][j];黑点连ed,流量ans-d[i][j];相邻的不同颜色的点相连,流量无限;那么只要看看是否满流就好啊。。。
注意上界有点大...
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define inf 999999999999999999
using namespace std;
typedef long long LL;
struct node
{
int x,y,next,other;LL c;
}a[];int len,last[];
void ins(int x,int y,LL c)
{
LL k1,k2;
k1=++len;
a[len].x=x;a[len].y=y;a[len].c=c;
a[len].next=last[x];last[x]=len; k2=++len;
a[len].x=y;a[len].y=x;a[len].c=;
a[len].next=last[y];last[y]=len; a[k1].other=k2;
a[k2].other=k1;
}
int list[],h[],st,ed,head,tail;
bool bt_h()
{
memset(h,,sizeof(h));h[st]=;
list[]=st;head=;tail=;
while(head!=tail)
{
int x=list[head];
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(h[y]== && a[k].c>)
{
h[y]=h[x]+;
list[tail++]=y;
}
}
head++;
}
if(h[ed]>)return true;
return false;
}
LL find_flow(int x,LL flow)
{
if(x==ed)return flow;
LL s=,t;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(h[y]==h[x]+ && a[k].c> && s<flow)
{
s+=t=find_flow(y,min(a[k].c,flow-s));
a[k].c-=t;a[a[k].other].c+=t;if(s==flow)break;
}
}
if(s==)h[x]=;
return s;
}
int T;
int n,m;
LL mp[][];int d[][];
bool f[][];//黑false白true染色
const int dx[]={,-,,,};
const int dy[]={,,,-,};
bool check(LL sum)
{
LL ret=;
len=;memset(last,,sizeof(last));st=n*m+,ed=st+;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(f[i][j]==true)ins(st,d[i][j],sum-mp[i][j]),ret+=sum-mp[i][j];
else ins(d[i][j],ed,sum-mp[i][j]);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)if(f[i][j]==true)
for(int k=;k<=;k++)
{
int tx=i+dx[k],ty=j+dy[k];
if(d[tx][ty]!=- && f[i][j]!=f[tx][ty])ins(d[i][j],d[tx][ty],inf);
}
LL ans=;while(bt_h())ans+=find_flow(st,inf);
return ret==ans?true:false;
}
LL sol(LL sum)
{
LL ans=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
ans+=(sum-mp[i][j]);
return ans/2LL;
}
int main()
{
scanf("%d",&T);while(T--)
{
LL cnt1=,cnt2=,sum1=,sum2=,maxx=;
scanf("%d%d",&n,&m);memset(mp,,sizeof(mp));memset(d,-,sizeof(d));memset(f,true,sizeof(f));
int ss=;for(int i=;i<=n;i++)for(int j=;j<=m;j++)d[i][j]=++ss;
for(int i=;i<=n;i++)for(int j=;j<=m;j++)scanf("%lld",&mp[i][j]),sum1+=mp[i][j],maxx=max(maxx,mp[i][j]);
for(int i=;i<=n;i++)
for(int j=i%+;j<=m;j+=)
f[i][j]=false,cnt2++,sum2+=mp[i][j];
sum1-=sum2;cnt1=n*m-cnt2;
if(cnt1==cnt2)
{
if(sum1!=sum2)printf("-1\n");
else
{
LL l=maxx,r=inf,ans=-;
while(l<=r)
{
LL mid=(l+r)/;
//if(mid<maxx)l=mid+1;
if(check(mid))r=mid-,ans=mid;
else l=mid+;
}
if(ans==-)printf("-1\n");
else printf("%lld\n",sol(ans));
}
}
else
{
LL ans=(sum1-sum2)/(cnt1-cnt2);
if(ans<maxx || check(ans)==false)printf("-1\n");
else printf("%lld\n",sol(ans));
}
}
return ;
}
bzoj2756: [SCOI2012]奇怪的游戏(网络流+分情况)的更多相关文章
- Bzoj2756 [SCOI2012]奇怪的游戏
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3220 Solved: 886 Description ...
- BZOJ 2756: [SCOI2012]奇怪的游戏 网络流/二分
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 1594 Solved: 396[Submit][Stat ...
- BZOJ2756 [SCOI2012]奇怪的游戏 【网络流 + 二分】
题目 Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻 的格子,并使这两个数都加上 1. 现在 Blinker 想知 ...
- BZOJ2756:[SCOI2012]奇怪的游戏(最大流,二分)
Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻 的格子,并使这两个数都加上 1. 现在 B ...
- BZOJ2756 SCOI2012奇怪的游戏(二分答案+最大流)
由数据范围容易想到网络流.由于操作只是对于棋盘上相邻两格,容易想到给其黑白染色. 假设已经知道最后要变成什么数.那么给黑白点之间连边,其流量则表示同时增加的次数,再用源汇给其限流为需要增加的数即可. ...
- BZOJ2756 [SCOI2012]奇怪的游戏 最大流
好久没有写博客了.不过这个博客也没有多少人看 最近在写网络流,为了加深理解,来写一两篇题解. 对整个棋盘进行黑白染色以后可以发现,一次操作就是让二分图的两个点的值分别 \(+1\). 这样,我们就可以 ...
- 【BZOJ2756】奇怪的游戏(二分,网络流)
[BZOJ2756]奇怪的游戏(二分,网络流) 题面 BZOJ Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blink ...
- bzoj 2756 [SCOI2012]奇怪的游戏 二分+网络流
2756:[SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 4926 Solved: 1362[Submit][Stat ...
- 【BZOJ-2756】奇怪的游戏 最大流 + 分类讨论 + 二分
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 2925 Solved: 792[Submit][Stat ...
随机推荐
- Android recovery UI实现分析
Android recovery模式为何物? 关于这个问题, baidu上已经有无数的答案.不理解的朋友先补习一下. 从纯技术角度来讲, recovery和android本质上是两个独立的rootfs ...
- Unreal Engine 4 C++ 为编辑器中Actor创建自己定义图标
有时候我们创建场景的时候,特定的Actor我们想给它一个特定的图标,便于观察.比方这样: 实现起来也非常easy.须要编写C++代码: 我们创建一个Actor,叫AMyActor.它包括一个Sprit ...
- 微信小程序发送模板消息
微信小程序发送模板消息 标签(空格分隔): php 看小程序文档 [模板消息文档总览]:https://developers.weixin.qq.com/miniprogram/dev/framewo ...
- Winform WPF 窗体显示位置
WinForm 窗体显示位置 窗体显示的位置首先由窗体的StartPosition决定,FormStartPosition这个枚举值由如下几种情况 // 摘要: // 窗体的位置由 System.Wi ...
- .NET MVC权限设计思考之切入点
在WebForm下我们一般会设计个PageBase继承Page,在OnInit方法中实现对基本权限的验证业务,然后所有的页面在继承PageBase直接继承这项基本权验证业务.而在.NET MVC下我们 ...
- 跨域-jsonp、cors、iframe、document.domain、postMessage()
同源策略 概念:同源: 协议.域名.端口号 完全相同 同源策略是浏览器的一种安全策略:且浏览器不会将违反同源策略的响应信息返回 http://127.0.0.1:3000/index.html ...
- 卡片式大学综合英语词汇(Windows Phone 8.1 RT app)
简易卡片式记单词app.词库是原滋原味的大学综合英语词汇,包含语音,使用卡片式设计.离线词库,随时随地记单词. 商店:http://www.windowsphone.com/zh-cn/store/a ...
- C语言-实现整数倒序输出
Action() { //实现一个3位数的倒序输出(123输出321) int n; int m=321; n=fun_mod(m,n); lr_output_message("%d&quo ...
- Aspose.Cells基础使用方法整理
Aspose.Cells 插件,将web端数据以excel形式导出到客户端. 相关文档: https://blog.csdn.net/djk8888/article/details/53065416 ...
- JWT加密
JWT是一种加密算法,为了防止请求的信息在传输途中被拦截修改 JWT的引用: install-package jwt JWF由三部分组成:Header,Payload,Signature Payloa ...