SCOI2012——奇怪的游戏(最大流+二分检验)
来源:互联网 发布:2015年双11淘宝交易额 编辑:程序博客网 时间:2024/06/05 08:04
2756: [SCOI2012]奇怪的游戏
Time Limit: 40 Sec Memory Limit: 128 MB
Submit: 490 Solved: 114
[Submit][Status][Discuss]
DescriptionBlinker最近喜欢上一个奇怪的游戏。
这个游戏在一个 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
Source
day2
解析:
将所有格子进行黑白染色。。。因为每次对相邻的两个格子加1,所以相邻的两个格子肯定属于二分图的两边。。。
然后一边的格子连源点,容量为我们二分出的所有格子最后变成的值x-map[i][j],另一边同样连汇点。。。中间相邻的格子连容量无穷的边。。。
以上是网络流建图部分。。。
首先,如果有奇数个格子。。。计算出黑白格子总和的差值diff,如果diff<maxw输-1
否者,跑最大流,如果能跑满,即flow(diff)==(diff*n*m-sum)>>1;输出等式右边部分,否者-1.。。
如果有偶数个格子。。。
我们可以证明当所有格子最后变成一个数成立,那么大于这个数的所有情况都成立。。。
于是很容易想到二分,分到一个值,如果满足就在左区间找否者就在右区间找。。。
注意本题会超int
ps:据说本题卡递归的sap,其实不是。。。我就是用递归sap,但需要小优化一下。。。要把sap的 if(d[0]>=l+2)return res;这句话放到循环里面
这儿太坑了,整整Debug了两天。。。
代码:
/************************************************************** Problem: 2756 User: jianing Language: C++ Result: Accepted Time:11884 ms Memory:3192 kb****************************************************************/ #include<cstdio>#include<algorithm>#include<cmath>#include<cstring>using namespace std;typedef long long LL;const LL inf=0x3f3f3f3f3f3f3f3fll;#define most 1000000000 int n,m,l=0,e=0;int map[50][50],val[2510];struct node{ int u,v,next; LL c;}edge[100000];int head[100000];int d[2500],sumd[2500];int maxx;LL sum1,sum2; void read(){ freopen("game.in","r",stdin); freopen("game.out","w",stdout);} void add(int u,int v,LL c){ edge[e].u=u; edge[e].v=v; edge[e].c=c; edge[e].next=head[u]; head[u]=e++; edge[e].u=v; edge[e].v=u; edge[e].c=0; edge[e].next=head[v]; head[v]=e++;} LL sap(int u,LL flow){ if(u==l+1)return flow; LL res=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(edge[i].c && d[u]==d[v]+1) { LL t=sap(v,(LL)min(edge[i].c,(flow-res))); res+=t; edge[i].c-=t;edge[i^1].c+=t; if(res==flow)return res; if(d[0]>=l+2)return res;//本来放在下面,T哭了 } // } // sumd[d[u]]--; //就这儿 if(sumd[d[u]]==0)d[0]=l+2; sumd[++d[u]]++; return res;} LL flow(LL x){ memset(head,-1,sizeof(head)); memset(edge,0,sizeof(edge)); e=0;l=n*m;int t=n*m+1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if((i+j)&1) { add(0,m*(i-1)+j,x-map[i][j]); if(i>1)add(m*(i-1)+j,m*(i-2)+j,inf); if(i<n)add(m*(i-1)+j,m*i+j,inf); if(j>1)add(m*(i-1)+j,m*(i-1)+j-1,inf); if(j<m)add(m*(i-1)+j,m*(i-1)+j+1,inf); } else add(m*(i-1)+j,t,x-map[i][j]); } memset(d,0,sizeof(d)); memset(sumd,0,sizeof(sumd)); sumd[0]=l+2; LL ans=0; while(d[0]<=l+1) ans+=sap(0,inf); return ans;} void check(){ LL best=inf; LL ll=(LL)maxx,rr=inf; while(ll<rr) { LL mid=(ll+rr)>>1; LL ans=flow(mid); LL tmp=mid*n*m-sum1-sum2; if(tmp==ans*2) { if(ans>0)best=min(best,ans); rr=mid; } else ll=mid+1; } printf("%lld\n",best);} LL max(LL a,LL b){ return a>b?a:b;} void work(){ e=0;maxx=0; sum1=0;sum2=0;int cnt1=0,cnt2=0; memset(map,0,sizeof(map)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { scanf("%d",&map[i][j]); maxx=max(maxx,map[i][j]); if((i+j)&1) { sum1+=map[i][j]; cnt1++; } else { sum2+=map[i][j]; cnt2++; } } if(cnt1!=cnt2) { if((sum1-sum2)%(cnt1-cnt2)!=0)printf("-1\n"); LL diff=(sum1-sum2)/(cnt1-cnt2); if(diff<maxx) { printf("-1\n"); return ; } else { LL ans=flow(diff); LL tmp=diff*n*m-sum1-sum2; if(tmp==ans*2)printf("%lld\n",ans); else printf("-1\n"); } } else check();} int main(){ // read(); int test; scanf("%d",&test); while(test--) work(); return 0;}
- SCOI2012——奇怪的游戏(最大流+二分检验)
- 【最大流】【二分检验】【SCOI2012】奇怪的游戏
- 【二分+最大流】[SCOI2012]奇怪的游戏 BZOJ2756
- bzoj2756: [SCOI2012]奇怪的游戏 二分+最大流
- 【最大流】【二分】[Scoi2012] bzoj2756 奇怪的游戏
- 【bzoj2756】【SCOI2012】【奇怪的游戏】【最大流+二分】
- bzoj2756[SCOI2012]奇怪的游戏 二分 分类讨论 最大流
- 【SCOI2012】【二分法】【最大流】奇怪的游戏
- 【BZOJ2756】【SCOI2012】奇怪的游戏 最大流、
- bzoj 2756: [SCOI2012]奇怪的游戏(网络流+二分)
- BZOJ2756 【scoi2012】奇怪的游戏(二分+网络流)
- Dinic最大流(bzoj 2756: [SCOI2012]奇怪的游戏)
- 【BZOJ 2756】[SCOI2012]奇怪的游戏 网络流+二分
- BZOJ 2756 [SCOI2012]奇怪的游戏 二分+网络流
- 【bzoj2756: [SCOI2012]奇怪的游戏】 二分+网络流判断
- SCOI2012[奇怪的游戏]
- [SCOI2012]奇怪的游戏 (网络流)
- bzoj2756: [SCOI2012]奇怪的游戏
- windows程序设计第五版 第六章 KEYVIEW1.c
- NOKIA真是被micsoft给害了
- C/C++浮点数在内存中的存储方式
- redis入门——安装
- 详谈高性能TCP服务器开发
- SCOI2012——奇怪的游戏(最大流+二分检验)
- redis入门——VMware 环境下的机群搭建与应用
- 每个开发人员都应该知道的8个Linux命令
- linux共享windows文件夹
- Matlab插值与拟合
- Javascript解决浏览器兼容性问题
- 对String和StringBuffer用法的理解
- 每天一个linux命令(46):vmstat命令
- OpenCV给图像添加柏林噪声