bzoj2756 [SCOI2012]奇怪的游戏
2017-08-15 17:21
183 查看
Description
Blinker最近喜欢上一个奇怪的游戏。这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数。每次 Blinker 会选择两个相邻的格子,并使这两个数都加上 1。
现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成同一个数则输出-1。
Input
输入的第一行是一个整数T,表示输入数据有T轮游戏组成。每轮游戏的第一行有两个整数N和M, 分别代表棋盘的行数和列数。
接下来有N行,每行 M个数。
Output
对于每个游戏输出最少能使游戏结束的次数,如果永远不能变成同一个数则输出-1。Sample Input
22 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
正解:二分+最大流。
这道题还是很不容易想啊,不过我写了个骗分居然有$90$分。。
首先我们肯定是要黑白染色,相邻的点染不同的颜色。
然后我们按照格子数分奇偶讨论:
如果格子数为偶数,那么黑点和白点个数相同,于是所有黑点的和与所有白点的和必须相同,否则一定不合法。
因为当黑点和白点个数相同时,每个点的权值$+1$,等价于将相邻的上下两点匹配一次,所以我们发现每个点的最终权值是满足单调性的。也就是说如果$v$合法,那么$v+1$也一定合法,于是我们直接二分最终的权值,建图跑最大流就行了。
当格子数为奇数时,黑点与白点个数不同。那么我们可以直接算出最终每个格子的权值。
由$v*num_{black}-sum_{black}=v*num_{white}-sum_{white}$,解得$v=(sum_{black}-sum_{while})/(num_{black}-num_{white})$。
$num$为格子数量,$sum$为初始的格子权值和。
那么我们判断一下$v$是否合法就行了。
#include <bits/stdc++.h> #define il inline #define RG register #define ll long long #define inf (1LL<<60) #define N (1000010) #define pos(i,j) ((i-1)*m+j) using namespace std; struct edge{ int nt,to; ll flow,cap; }g[N<<1]; int head ,d ,q ,a[42][42],S,T,n,m,num,tot; ll x,y,ans; il int gi(){ RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; } il void insert(RG int from,RG int to,RG ll cap){ g[++num]=(edge){head[from],to,0,cap},head[from]=num; return; } il int bfs(RG int S,RG int T){ for (RG int i=1;i<=T;++i) d[i]=0; RG int h=0,t=1; q[t]=S,d[S]=1; while (h<t){ RG int x=q[++h],v; for (RG int i=head[x];i;i=g[i].nt){ v=g[i].to; if (!d[v] && g[i].cap>g[i].flow){ d[v]=d[x]+1,q[++t]=v; if (v==T) return 1; } } } return d[T]; } il ll dfs(RG int x,RG int T,RG ll a){ if (!a || x==T) return a; RG ll flow=0,f; RG int v; for (RG int i=head[x];i;i=g[i].nt){ v=g[i].to; if (d[v]==d[x]+1 && g[i].cap>g[i].flow){ f=dfs(v,T,min(a,g[i].cap-g[i].flow)); if (!f){ d[v]=0; continue; } g[i].flow+=f,g[i^1].flow-=f; flow+=f,a-=f; if (!a) return flow; } } return flow; } il ll maxflow(RG int S,RG int T){ RG ll flow=0; while (bfs(S,T)) flow+=dfs(S,T,inf); return flow; } il int check(RG ll key){ for (RG int i=1;i<=T;++i) head[i]=0; num=1; for (RG int i=1;i<=n;++i) for (RG int j=1;j<=m;++j){ if ((i+j)&1) insert(S,pos(i,j),key-a[i][j]),insert(pos(i,j),S,0); else insert(pos(i,j),T,key-a[i][j]),insert(T,pos(i,j),0); } for (RG int i=1;i<=n;++i) for (RG int j=1;j<=m;++j) if ((i+j)&1){ if (i>1) insert(pos(i,j),pos(i-1,j),inf),insert(pos(i-1,j),pos(i,j),0); if (i<n) insert(pos(i,j),pos(i+1,j),inf),insert(pos(i+1,j),pos(i,j),0); if (j>1) insert(pos(i,j),pos(i,j-1),inf),insert(pos(i,j-1),pos(i,j),0); if (j<m) insert(pos(i,j),pos(i,j+1),inf),insert(pos(i,j+1),pos(i,j),0); } maxflow(S,T); for (RG int i=1,k=2;i<=n;++i) for (RG int j=1;j<=m;++j,k+=2) if (g[k].flow!=g[k].cap) return 0; return 1; } il void work(){ n=gi(),m=gi(),tot=x=y=0,S=n*m+1,T=S+1; for (RG int i=1;i<=n;++i) for (RG int j=1;j<=m;++j){ a[i][j]=gi(),tot=max(tot,a[i][j]); if ((i+j)&1) x+=a[i][j]; else y+=a[i][j]; } if (n*m%2==0){ if (x!=y){ puts("-1"); return; } RG ll l=tot,r=1LL<<50,mid; while (l<=r){ mid=(l+r)>>1; if (check(mid)) ans=mid,r=mid-1; else l=mid+1; } printf("%lld\n",(ans*n*m>>1)-x); } else{ RG ll X=y-x; if (X<tot){ puts("-1"); return; } if (check(X)) printf("%lld\n",X*((n*m)>>1)-x); else puts("-1"); } return; } int main(){ #ifndef ONLINE_JUDGE freopen("game.in","r",stdin); freopen("game.out","w",stdout); #endif RG int T=gi(); while (T--) work(); return 0; }
相关文章推荐
- bzoj2756 [SCOI2012]奇怪的游戏
- bzoj2756 [SCOI2012]奇怪的游戏
- bzoj2756[SCOI2012]奇怪的游戏 二分 分类讨论 最大流
- Bzoj2756 [SCOI2012]奇怪的游戏
- bzoj 2756: [SCOI2012]奇怪的游戏
- BZOJ2756 [SCOI2012]奇怪的游戏 【网络流 + 二分】
- bzoj2756 [SCOI2012]奇怪的游戏 结论+网络流
- [SCOI2012]奇怪的游戏 (网络流)
- 【最大流】【二分】[Scoi2012] bzoj2756 奇怪的游戏
- 【SCOI2012】bzoj2756 奇怪的游戏
- [BZOJ2756][SCOI2012]奇怪的游戏
- BZOJ 2756: [SCOI2012]奇怪的游戏
- BZOJ 2756 SCOI 2012 奇怪的游戏 二分+最大流
- BZOJ 2756 [SCOI2012]奇怪的游戏
- BZOJ 2756 [SCOI2012]奇怪的游戏
- bzoj 2756: [SCOI2012]奇怪的游戏(网络流+二分)
- 【最大流】【二分检验】【SCOI2012】奇怪的游戏
- BZOJ 2756 【SCOI2012】 奇怪的游戏
- bzoj2756: [SCOI2012]奇怪的游戏
- Dinic最大流(bzoj 2756: [SCOI2012]奇怪的游戏)