【BZOJ2756】奇怪的游戏,网络流判断答案
来源:互联网 发布:dijkstra算法 poj 编辑:程序博客网 时间:2024/06/14 21:24
Time:2016.08.15
Author:xiaoyimi
转载注明出处谢谢
传送门
思路:
首先考虑黑白染色
设最终所有格子的数字都是x
那么到最后黑格子和白格子的增量都是一样的
设起始黑格子共有num1个,数字总和为sum1,白格子共有num2个,数字总和为sum2
那么num1*x-sum1=num2*x-sum2
然后呢?
分类讨论
黑白点数不相等时(num1!=num2)(即n*m为奇数时)
显然有
所以我们只要判断最终答案是不是x就可以了
黑白点数相等时(num1=num2)(即n*m为偶数时)
x就不唯一了
我们要求出最小的x
显然x+1,x+2..都是可以了
考虑二分答案
如何用网络流判断x?
S向黑点(i,j)连边,流量为x-w(i,j)
白点(i,j)连边,流量为x-w(i,j)
黑点向四周的白点连边,流量inf
答案可行的条件是满流
也就是最大流等于∑x-w(i,j)
最终输出答案就是x*num1-sum1
注意:
无解条件
n*m为奇数时x小于max(w(i,j))或网络流check失败
n*m为偶数时sum1!=sum2或网络流check失败
代码:
#include<cstdio>#include<iostream>#include<queue> #include<cstring>#define LL long long#define pd(i,j) (1<=i&&i<=n&&1<=j&&j<=m)#define inf 1LL<<60using namespace std;int T,n,m,s,t,tot;int a[42][42],first[1605],dis[1605];int dx[4]={0,0,-1,1},dy[4]={-1,1,0,0};queue <int> q; struct edge{ int v,next; LL w;}e[20005];int in(){ int t=0;char ch=getchar(); while (!isdigit(ch)) ch=getchar(); while (isdigit(ch)) t=(t<<1)+(t<<3)+ch-48,ch=getchar(); return t;}void add(int x,int y,LL z){ e[++tot]=(edge){y,first[x],z};first[x]=tot; e[++tot]=(edge){x,first[y],0};first[y]=tot;}bool bfs(){ memset(dis,0,sizeof(dis)); dis[s]=1;q.push(s); for (;!q.empty();q.pop()) { int k=q.front(); for (int i=first[k];i;i=e[i].next) if (!dis[e[i].v]&&e[i].w) dis[e[i].v]=dis[k]+1, q.push(e[i].v); } return dis[t];}LL dfs(int x,LL mx){ if (x==t) return mx; LL k,used=0; for (int i=first[x];i;i=e[i].next) if (dis[e[i].v]==dis[x]+1) { k=dfs(e[i].v,min(e[i].w,mx-used)); e[i].w-=k;e[i^1].w+=k; used+=k; if (used==mx) return mx; } if (!used) dis[x]=0; return used;}bool check(LL flow){ memset(first,0,sizeof(first)); tot=1; LL cnt=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { if (i+j&1) { add(s,(i-1)*m+j,flow-a[i][j]); cnt+=flow-a[i][j]; for (int k=0;k<4;k++) if (pd(i+dx[k],j+dy[k])) add((i-1)*m+j,(i-1+dx[k])*m+j+dy[k],inf); } else add((i-1)*m+j,t,flow-a[i][j]); } while (bfs()) cnt-=dfs(s,inf); return !cnt;}main(){ for (T=in();T;T--) { n=in();m=in(); t=n*m+1; int mx=0; LL sum1=0,sum2=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { a[i][j]=in(), mx=max(mx,a[i][j]); if (i+j&1) sum1+=a[i][j]; else sum2+=a[i][j]; } if (n*m&1) if(sum2-sum1>=mx&&check(sum2-sum1)) printf("%lld\n",(sum2-sum1)*(n*m/2)-sum1); else puts("-1"); else { if (sum2!=sum1) {puts("-1");continue;} LL l=mx,r=inf,mid,ans=0; for (mid=l+r>>1;l<=r;mid=l+r>>1) if (check(mid)) r=mid-1,ans=mid; else l=mid+1; printf("%lld\n",ans*(n*m/2)-sum1); } }}
0 0
- 【BZOJ2756】奇怪的游戏,网络流判断答案
- 【bzoj2756: [SCOI2012]奇怪的游戏】 二分+网络流判断
- BZOJ2756 【scoi2012】奇怪的游戏(二分+网络流)
- 【BZOJ2756】【SCOI2012】奇怪的游戏 最大流、
- bzoj2756: [SCOI2012]奇怪的游戏
- [BZOJ2756][SCOI2012]奇怪的游戏
- BZOJ2756/SCOI2012 奇怪的游戏
- bzoj2756 [SCOI2012]奇怪的游戏
- bzoj2756 [SCOI2012]奇怪的游戏
- bzoj2756 [SCOI2012]奇怪的游戏
- 【SCOI2012】bzoj2756 奇怪的游戏
- bzoj2756 [SCOI2012]奇怪的游戏
- BZOJ2756 [SCOI2012]奇怪的游戏
- 【二分+最大流】[SCOI2012]奇怪的游戏 BZOJ2756
- bzoj2756: [SCOI2012]奇怪的游戏 二分+最大流
- 【最大流】【二分】[Scoi2012] bzoj2756 奇怪的游戏
- 【bzoj2756】【SCOI2012】【奇怪的游戏】【最大流+二分】
- bzoj2756[SCOI2012]奇怪的游戏 二分 分类讨论 最大流
- 0203 - 应用组件 - Activity
- erlang 故障排查工具
- 8大排序之-----(3)选择排序与时间复杂度
- CodeForces 535C Tavas and Karafs
- Spring MVC3 + Velocity设置favicon
- 【BZOJ2756】奇怪的游戏,网络流判断答案
- tar
- Spring的生命周期
- Linux系统调用与文件I/O(一)(2)
- A + B Problem II 大数相加(可以作为模板题)
- Android NestedScrolling机制完全解析 带你玩转嵌套滑动
- XML的特殊字符处理
- python数据类型篇
- LightOJ 1265