这个题的数据,太卡了,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;elsereturn 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;
}

转载于:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5346227.html

BZOJ-2756 奇怪的游戏 黑白染色+最大流+当前弧优化+二分判断+分类讨论相关推荐

  1. bzoj 2756奇怪的游戏

    2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MB Submit: 2571  Solved: 685 [Submit][St ...

  2. [BZOJ 2756] 奇怪的游戏

    Link:https://www.lydsy.com/JudgeOnline/problem.php?id=2756 Algorithm: 比较新颖的题目 首先发现是对矩阵中相邻两数进行操作    & ...

  3. bzoj 2756 [SCOI2012]奇怪的游戏 二分+网络流

    2756:[SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MB Submit: 4926  Solved: 1362 [Submit][St ...

  4. Dinic最大流(bzoj 2756: [SCOI2012]奇怪的游戏)

    Dinic算法: 转一张很好懂的图,复杂度O(V²E) 注意一开始的那个层次图并不是原图,是第一次bfs时所保留的边 (像原图中1和2之间也有一条边,不过第一次bfs时这条边并不会被经过) 2756: ...

  5. 广度优先搜索——好奇怪的游戏(洛谷 P1747)

    题目选自洛谷P1747 简单的广搜模板题,4+8 = 12个方向进行bfs,目的地是(1,1) 每次查看队首是否到达,若到达(1,1) 则返回队首步长即可~ 需要注意的是,马走日和像走田的位置计算 i ...

  6. P1747 好奇怪的游戏

    题目背景 <爱与愁的故事第三弹·shopping>娱乐章. 调调口味来道水题. 题目描述 爱与愁大神坐在公交车上无聊,于是玩起了手机.一款奇怪的游戏进入了爱与愁大神的眼帘:***(游戏名被 ...

  7. 好奇怪的游戏(洛谷)

    题目背景 <爱与愁的故事第三弹·shopping>娱乐章. 调调口味来道水题. 题目描述 爱与愁大神坐在公交车上无聊,于是玩起了手机. 一款奇怪的游戏进入了爱与愁大神的眼帘:***(游戏名 ...

  8. 洛谷P1747-好奇怪的游戏(BFS)

    题目背景: <爱与愁的故事第三弹·shopping>娱乐章. 调调口味来道水题. 题目描述: 爱与愁大神坐在公交车上无聊,于是玩起了手机.一款奇怪的游戏进入了爱与愁大神的眼帘:***(游戏 ...

  9. 【Python】P1747 好奇怪的游戏

    题目背景 <爱与愁的故事第三弹·shopping>娱乐章. 调调口味来道水题. 题目描述 爱与愁大神坐在公交车上无聊,于是玩起了手机.一款奇怪的游戏进入了爱与愁大神的眼帘:***(游戏名被 ...

最新文章

  1. Python说“万能钥匙”不可见密码,立马写了个脚本解决了
  2. 250鲁大师跑分_看了鲁大师跑分,会发现MX250独显笔记本已落伍了
  3. 我要当皇帝等微信小游戏的wbs
  4. python必刷面试_Python面试必刷题系列(5)
  5. 深度学习tensorflow实现宝可梦图像分类
  6. echart 三维可视化地图_揭秘720°三维全景3D实景地图制作技术
  7. 将桌面文件动态保存到D盘
  8. wpf,后台触发按钮点击以及拖动
  9. 超硬核!只要1美元!教你给MacBook装上触摸屏
  10. linux进程(线程间)间通信-eventfd
  11. 基于LDA的文本主题聚类Python实现
  12. Sql Server 2008R2 备份文件还原数据库
  13. 使用通达信一次性获取沪深300成分股
  14. Towards a new generation of artificial intelligence in China
  15. 批量导入AD账户批量启用Exchange 账户步骤
  16. 区块链技术应用后,不再需要CA认证机构
  17. 解释耳语协议和 Status.im
  18. 湘潭大学计算机考研拟录取,湘潭大学2019年硕士研究生拟录取考生公示名单
  19. 为什么反向传播更加高效
  20. Linuxnbsp;用命令行打开docnbsp;pdf…

热门文章

  1. 此域的推荐安全级别是“安全级-高”的解决办法
  2. 单循环链表(C语言实现)
  3. ARM中Steppingstone启动
  4. php自动维护,完全禁用关闭Windows Server 2012R2自动维护功能禁用WIN2012R2自动维护
  5. 第七章_类_7.4 类的作用域(加了自己的总结部分)
  6. c++内存管理-内存顺序
  7. bootstrap 起步
  8. struts2.2.1关于sitemesh和freemarker整合的细节
  9. struts2 去掉或修改后缀名
  10. linux egrep新添的正则表达式元字符