BZOJ-2756 奇怪的游戏 黑白染色+最大流+当前弧优化+二分判断+分类讨论
2016-01-14 00:02
459 查看
这个题的数据,太卡了,TLE了两晚上,各种调试优化,各种蛋疼。
2756: [SCOI2012]奇怪的游戏
Time Limit: 40 Sec Memory Limit: 128 MB
Submit: 2311 Solved: 598
[Submit][Status][Discuss]
Description
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
Source
这道题一看到,还真没直接想到网络流,看了看每次必须找相邻两个点,偶然想到国际象棋,于是黑白染色;
于是统计出wnum,bnum,wsum,bsum(染成White的格子数,和初始的总数,及染成Black的格子数和初始总数)
二分最后的结果X(x为满足所有格子都一样时的格子中的数),所以可以得到下面的一个关系式:
X * wnum - wsum = X * bnum - bsum ==> X * bnum - X * wnum = bsum - wsum ==> X = (bsum - wsum)/(bnum - wnum)
每次相邻两个+1可知,每次必然满足wsum+1,bsum+1;
所以我们得到 当 bnum==wnum 时,如果满足bsum!=wsum 则无解
当 bsum==wsum 时,如果x成立,则任何>=x的数都成立,所以二分X即可
当 bnum!=wnum 时,发现至多有一个解,所以解得X,判断是否符合即可
建图:
超级源S向每个白点连边,边权为X-white【i】;
每个白点向相邻的黑点连边,边权为INF;
每个黑点向超级汇T连边,边权为X-black【i】;
(X为二分出的值,white【】,black【】表示初始值)
用tot记录差值,判断最大流是否满足即可
值得注意的是这个题的 时间限制,以及long long。
code:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define maxl (1LL<<50) #define zb(x,y) (x-1)*m+y int dis[2005]; struct data{ int next,to; long long v; }edge[10005]; int cnt=1,head[2005]={0}; int q[2005],h,t; int jz[50][50]={0}; int cur[2005]; int n,m,tim; int wnum,bnum; long long wsum,bsum; int num; int mx=0; long long tot=0; bool zt[50][50]; int move[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; void add(int u,int v,long long w) { cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].v=w; } void insert(int u,int v,long long w) { add(u,v,w);add(v,u,0); } 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; } void init() { n=read(); m=read(); for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) { jz[i][j]=read(); zt[i][j]=(i+j)&1; mx=max(mx,jz[i][j]); } num=n*m+1; for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) if (zt[i][j]) {wnum++;wsum+=jz[i][j];} else {bnum++;bsum+=jz[i][j];} } void make(long long mv) { cnt=1;memset(head,0,sizeof(head)); for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) if (zt[i][j]) { insert(0,zb(i,j),mv-jz[i][j]);tot+=mv-jz[i][j]; for (int k=0; k<4; k++) { int x=i+move[k][0],y=j+move[k][1]; if (x>0 && x<=n && y>0 && y<=m) insert(zb(i,j),zb(x,y),maxl); } } else insert(zb(i,j),num,mv-jz[i][j]); } bool bfs() { memset(dis,-1,sizeof(dis)); q[1]=0; dis[0]=1; h=0;t=1; while (h<t) { int j=q[++h],i=head[j]; while (i) { if (edge[i].v>0 && dis[edge[i].to]<0) { dis[edge[i].to]=dis[j]+1; q[++t]=edge[i].to; } i=edge[i].next; } } if (dis[num]>0) return true; else return false; } long long dfs(int loc,long long low) { if(loc==num)return low; long long flow,cost=0; for(int i=cur[loc];i;i=edge[i].next) if(dis[edge[i].to]==dis[loc]+1) { flow=dfs(edge[i].to,min(low-cost,edge[i].v)); edge[i].v-=flow;edge[i^1].v+=flow; if(edge[i].v) cur[loc]=i; cost+=flow;if(cost==low)return low; } if(!cost)dis[loc]=-1; return cost; } long long dinic() { long long temp=0; while (bfs()) { for (int i=0; i<=num; i++) cur[i]=head[i]; temp+=dfs(0,maxl); } return temp; } bool check(long long ans) { tot=0; make(ans); long long temp=dinic(); if (temp==tot) return 1; return 0; } int main() { tim=read(); while (tim--) { wnum=bnum=0;wsum=bsum=0;mx=0; init(); if (wnum==bnum) { if (wsum!=bsum) {puts("-1");continue;} long long left=mx; long long right=maxl; while (left<=right) { long long mid=(left+right)/2; if (check(mid)) right=mid-1; else left=mid+1; } printf("%lld\n",left*wnum-wsum); } else { long long x=(bsum-wsum)/(bnum-wnum); if (x>=mx) { if (check(x)) {printf("%lld\n",(x*wnum)-wsum);continue;} else puts("-1"); } else puts("-1"); } } return 0; }
相关文章推荐
- scala 第一天作业
- 图片加载到内存优化
- 【iOS开发】值对象--NSValue,NSNumber
- TableView滑动不加载
- TableView文字自适应高度
- linux系统下查看文件中含某个字符串
- webservice之通过wsdl文件生成客户端
- 利用jquery监控滚动条动态加载数据
- MySQL 数据库主从复制架构
- 加密证书介绍
- Zookeeper 入门示例
- 一款基于visual studio的代码模板定制与代码生成的插件分享
- 厦门巨游网络科技有限公司(HOTPOWER)承接游戏UI外包
- Zbrush怎样用brush菜单
- 2016/01/14 VBA学习9
- 蜂窝教育:浅谈IT人才就业前景
- Common Lisp 宏
- java类加载机制与反射
- joomla第一单元第二节《发表一篇文章》
- joomla第一单元第三节。备份与还原