Bzoj2756 [SCOI2012]奇怪的游戏
2016-12-08 18:03
316 查看
2756: [SCOI2012]奇怪的游戏
Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3220 Solved: 886
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
最大流。
对原图进行二分图染色,统计黑白格子的个数和各自的数量和。
每次加值,肯定是黑白格子各+1
设最终数值为D,得到:
D*cntW-sumW == D*cntB - sumB
如果格子数为奇数,也就是黑白格子不等,D是唯一的,只需要建立流量网络验证是否可行即可。
如果格子数为偶数: 如果sum不等,无解,否则可以二分D,验证是否可行并记录答案。
建图方法:
S到白格子连边,容量为D-格子权值
白格子到四周黑格子连边,容量为INF
黑格子到T连边,容量为D-格子权值
_____________
然后就愉快地WA了一串,调了好久好久。在那么一个瞬间察觉到哪里不对,再一看代码……我的init函数放在了二分前面,处理奇数情况时好像没调用?
23333翻出了第一次提交的记录,代码复制出来,换了init的位置,AC
233333这好像是第三次没有初始化了,第一次是某次写LCA,第二次是网络流
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<vector> #define LL long long using namespace std; const int mx[5]={0,1,0,-1,0}; const int my[5]={0,0,1,0,-1}; const int mxn=3010; int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } struct edge{int v,nxt;LL f;}e[mxn<<3]; int hd[mxn],mct=1; void add_edge(int u,int v,LL f){ e[++mct].v=v;e[mct].f=f;e[mct].nxt=hd[u];hd[u]=mct;return; } void ins(int u,int v,LL f){add_edge(u,v,f);add_edge(v,u,0);return;} int n,m,S,T; int mp[45][45]; int id[45][45]; int d[mxn]; bool BFS(){ memset(d,0,sizeof d); queue<int>q; d[S]=1; q.push(S); while(!q.empty()){ int u=q.front();q.pop(); for(int i=hd[u];i;i=e[i].nxt){ int v=e[i].v; if(!d[v] && e[i].f){ d[v]=d[u]+1; q.push(v); } } } return d[T]; } LL DFS(int u,LL lim){ if(u==T)return lim; LL tmp,f=0; for(int i=hd[u];i;i=e[i].nxt){ int v=e[i].v; if(d[v]==d[u]+1 && e[i].f){ tmp=DFS(v,min(lim,e[i].f)); e[i].f-=tmp; e[i^1].f+=tmp; lim-=tmp; f+=tmp; if(!lim)return f; } } d[u]=0; return f; } LL Dinic(){ LL res=0; while(BFS())res+=DFS(S,1e16); return res; } void init(){ for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) id[i][j]=(i-1)*m+j; return; } LL ans=0; bool solve(LL lim){ memset(hd,0,sizeof hd); mct=1; int i,j; LL tar=0; for(i=1;i<=n;i++) for(j=1;j<=m;j++){ if((i+j)%2==0){ ins(S,id[i][j],lim-mp[i][j]); tar+=lim-mp[i][j]; for(int k=1;k<=4;k++){ int nx=i+mx[k]; int ny=j+my[k]; if(nx>0 && nx<=n && ny>0 && ny<=m){ ins(id[i][j],id[nx][ny],1e16); } } } else{ins(id[i][j],T,lim-mp[i][j]);} } if(Dinic()==tar){ ans=tar; return 1; } return 0; } int main() { int Cas=read(); int i,j; while(Cas--){ int mxnum=-1e9; n=read();m=read(); for(i=1;i<=n;i++) for(j=1;j<=m;j++){ mp[i][j]=read(); mxnum=max(mxnum,mp[i][j]); } S=0;T=n*m+1; init(); LL numw=0,numb=0,cntw=0,cntb=0; for(i=1;i<=n;i++) for(j=1;j<=m;j++){ if((i+j)%2==0){ numw+=mp[i][j];cntw++; } else{ numb+=mp[i][j];cntb++; } } if(n*m%2==1){ LL D=(numw-numb)/(cntw-cntb); if(D>=mxnum && solve(D)){printf("%lld\n",ans);} else printf("-1\n"); continue; } else{ if(numb!=numw){ printf("-1\n"); continue; } ans=-1; LL l=mxnum,r=1e16; while(l<=r){ LL mid=(l+r)>>1; if(solve(mid)){ r=mid-1; } else l=mid+1; } printf("%lld\n",ans); } } return 0; }
相关文章推荐
- 【bzoj2756】【SCOI2012】【奇怪的游戏】【最大流+二分】
- 【SCOI2012】bzoj2756 奇怪的游戏
- bzoj 2756: [SCOI2012]奇怪的游戏
- bzoj2756 [SCOI2012]奇怪的游戏
- bzoj 2756 [SCOI2012]奇怪的游戏【二分+最大流】
- Dinic最大流(bzoj 2756: [SCOI2012]奇怪的游戏)
- [BZOJ2756][SCOI2012]奇怪的游戏
- BZOJ2756: [SCOI2012]奇怪的游戏(网络流)(还差代码)
- 【最大流】【二分】[Scoi2012] bzoj2756 奇怪的游戏
- [SCOI2012][BZOJ2756] 奇怪的游戏
- BZOJ 2756 【SCOI2012】 奇怪的游戏
- BZOJ2756 [SCOI2012]奇怪的游戏 【网络流 + 二分】
- BZOJ2756 【scoi2012】奇怪的游戏(二分+网络流)
- bzoj2756: [SCOI2012]奇怪的游戏
- bzoj2756: [SCOI2012]奇怪的游戏
- BZOJ2756 [SCOI2012]奇怪的游戏 【网络流 + 二分】
- bzoj2756 [SCOI2012]奇怪的游戏
- 【BZOJ2756】【SCOI2012】奇怪的游戏 最大流、
- BZOJ 2756 SCOI2012 奇怪的游戏
- BZOJ 2756: [SCOI2012]奇怪的游戏 [最大流 二分]