BZOJ 2756 SCOI2012 奇怪的游戏
2017-08-10 16:00
330 查看
2756: [SCOI2012]奇怪的游戏
Time Limit: 40 Sec Memory Limit: 128 MBDescription
Blinker最近喜欢上一个奇怪的游戏。
这个游戏在一个 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
分析:
首先我们考虑对棋盘黑白染色,那么我们发现:“每次相邻两个+1”,显然是一黑一白 +1
那么我们先统计出WhiteNum,BlackNum(黑白点的数目),WhiteSum,BlackSum(黑白点初始权值和)
那么对于一次增加,显然是WhiteSum+1,BlackSum+1
考虑对最后的情况进行讨论:
那么很显然,当WhiteNum==BlackNum时(即总点数为偶数)
如果WhiteSum!=BlackSum,显然无解
如果WhiteSum==BlackSum时,我们发现,对于X如果成立,那么X+1一定成立,显然满足二分的性质,那么二分这个值,进行判定
当WhiteNum!=BlackNum时(即总点数为奇数)
发现显然,若有解,则解唯一,那么直接验证正确性即可
至于解怎么求?
那么假设我们知道最后值为X,那么显然可以得到X∗WhiteNum−WhiteSum=X∗BlackNum−BlackSum
移项后显然可以化减出,eeeee,公式有点难写,自己化去吧
那么考虑建图:
S–>白点,约束为X-val[i][j]
黑点–>T,约束为X-val[i][j]
相邻的白点–>黑点,约束为INF
判断是否满流即可
#include<iostream> #include<cstring> #include<queue> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; inline int read(int &x){ x=0;int f=1;char c=getchar(); while(c>'9'||c<'0'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9'){ x=(x<<1)+(x<<3)+(c-'0'); c=getchar(); } x*=f; } #define MAXM 1001000 #define LL long long #define MAXN 2010 int Cas,m,n,mat[50][50]; struct Edge{ int to,next;LL val; }e[MAXM]; int head[MAXN],tot=1; inline void Add_Edge(int u,int v,LL w){ e[++tot].to=v;e[tot].val=w; e[tot].next=head[u];head[u]=tot; } inline void Insert_Edge(int u,int v,LL w){ Add_Edge(u,v,w);Add_Edge(v,u,0); } int dep[MAXN],cur[MAXN],S,T; queue<int> q; bool BFS(){ while(!q.empty()) q.pop(); memset(dep,-1,sizeof dep ); q.push(S);dep[S]=0; while(!q.empty()){ int u=q.front();q.pop(); for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(e[i].val&&dep[v]==-1){ dep[v]=dep[u]+1;q.push(v); } } } return dep[T]!=-1; } #define INF 1LL<<60 inline bool ok(int x,int y){ return (x>=1&&x<=n&&y>=1&&y<=m); } inline void init(){ tot=1;memset(head,0,sizeof head ); } int col[50][50],id[50][50]; LL Sum_b,Sum_w,Num_w,Num_b,ID; LL DFS(int u,LL flow){ if(u==T) return flow; LL ret=0; for(int i=cur[u];i;i=e[i].next){ int v=e[i].to; if(e[i].val&&dep[v]==dep[u]+1){ LL w=DFS(v,min(flow-ret,e[i].val)); e[i].val-=w;e[i^1].val+=w;ret+=w; if(e[i].val) cur[u]=i; if(ret==flow) return ret; } } if(!ret) dep[u]=-1; return ret; } LL Dinic(){ LL ret=0; while(BFS()){ for(int i=S;i<=T;i++) cur[i]=head[i]; ret+=DFS(S,INF); } return ret; } bool Check(LL x){ LL Tot=0; init(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ if(col[i][j]){ Insert_Edge(S,id[i][j],x-mat[i][j]);Tot+=(x-mat[i][j]); if(ok(i-1,j)) Insert_Edge(id[i][j],id[i-1][j],INF); if(ok(i,j-1)) Insert_Edge(id[i][j],id[i][j-1],INF); if(ok(i,j+1)) Insert_Edge(id[i][j],id[i][j+1],INF); if(ok(i+1,j)) Insert_Edge(id[i][j],id[i+1][j],INF); } else Insert_Edge(id[i][j],T,x-mat[i][j]); } LL ans=Dinic(); return Tot==ans; } void Build(){ S=0; T=n*m+1; Sum_b = Sum_w = Num_b = Num_w = 0; ID=0; int maxx=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) col[i][j]=(i+j)&1,id[i][j]= ++ID,maxx=max(maxx,mat[i][j]); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ if(col[i][j]) Sum_w += mat[i][j],Num_w++; else Sum_b += mat[i][j],Num_b++; } if(Num_w==Num_b&&Sum_b!=Sum_w){ puts("-1");return; } if(Num_w==Num_b){ LL l=maxx,r=(1LL<<50); while(l<=r){ LL Mid=(l+r)>>1; if(Check(Mid)) r=Mid-1; else l=Mid+1; } printf("%lld\n",l*Num_w-Sum_w); } else { LL x=(Sum_b-Sum_w)/(Num_b-Num_w); if(x<maxx) {puts("-1");return;} if(Check(x)) printf("%lld\n",x*Num_w-Sum_w); else puts("-1"); } } int main(){ read(Cas); while(Cas--){ read(n); read(m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) read(mat[i][j]); Build(); } return 0; }
相关文章推荐
- BZOJ 2756: [SCOI2012]奇怪的游戏
- BZOJ 2756: [SCOI2012]奇怪的游戏 [最大流 二分]
- [SCOI2012][BZOJ2756] 奇怪的游戏
- bzoj2756: [SCOI2012]奇怪的游戏
- bzoj2756: [SCOI2012]奇怪的游戏
- BZOJ 2756 [SCOI2012]奇怪的游戏 二分+网络流
- bzoj2756 [SCOI2012]奇怪的游戏
- bzoj2756 [SCOI2012]奇怪的游戏
- 【BZOJ 2756】[SCOI2012]奇怪的游戏 网络流+二分
- 【二分+最大流】[SCOI2012]奇怪的游戏 BZOJ2756
- BZOJ 2756 [SCOI2012]奇怪的游戏
- bzoj 2756: [SCOI2012]奇怪的游戏(网络流+二分)
- BZOJ 2756 [SCOI2012]奇怪的游戏
- bzoj 2756 [SCOI2012]奇怪的游戏【二分+最大流】
- BZOJ2756: [SCOI2012]奇怪的游戏(网络流)(还差代码)
- 【bzoj2756】【SCOI2012】【奇怪的游戏】【最大流+二分】
- Dinic最大流(bzoj 2756: [SCOI2012]奇怪的游戏)
- bzoj 2756: [SCOI2012]奇怪的游戏
- BZOJ 2756: [SCOI2012]奇怪的游戏 网络流/二分
- bzoj2756 [SCOI2012]奇怪的游戏