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

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

  1. bzoj 2756奇怪的游戏

    2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MB Description Blinke 最近喜欢上一个奇怪的游戏. 这个游戏 ...

  2. [BZOJ 2756] 奇怪的游戏

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

  3. BZOJ 2756 奇怪的游戏(最大流)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2756 题意:在一个 N*M 的棋盘上玩,每个格子有一个数.每次 选择两个相邻的格子,并使 ...

  4. BZOJ.2756.[SCOI2012]奇怪的游戏(二分 黑白染色 最大流ISAP)

    题目链接 \(Description\) \(Solution\) 这种题当然要黑白染色.. 两种颜色的格子数可能相同,也可能差1.记\(n1/n2\)为黑/白格子数,\(s1/s2\)为黑/白格子权 ...

  5. bzoj 1324 Exca王者之剑(黑白染色,最小割)

    [题意] 两相邻点不能同时选,选一个点集使得权值和最大. 出题人语文好... [思路] 将图进行黑白二染色,然后构建最小割模型. [代码] #include<set> #include&l ...

  6. bzoj 3240: [Noi2013]矩阵游戏 矩阵乘法+十进制快速幂+常数优化

    3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 613  Solved: 256[Submit][Status] ...

  7. BZOJ 2756 【SCOI2012】 奇怪的游戏

    题目链接:奇怪的游戏 一开始这道题想岔了……想到黑白染色后对总格子数按奇偶性分类讨论,然后没发现奇数个格子的可以直接解方程…… 首先可以发现每次操作是给相邻的两个格子权值加一,因此我们把棋盘黑白染色后 ...

  8. BZOJ 2756: [SCOI2012]奇怪的游戏 [最大流 二分]

    2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 3352  Solved: 919[Submit][Stat ...

  9. BZOJ 2756 SCOI2012 奇怪的游戏 最大流

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2756 Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N ...

随机推荐

  1. 第2章 面向对象的设计原则(SOLID):4_接口隔离原则(ISP)

    4. 接口隔离原则(Interface Segregation Principle,ISP) 4.1 定义 (1)使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口.类间的 ...

  2. 注册其它地区Apple ID

    不同地区Apple Id需求 iPhone 最近换上了iPhone,想要下载其它国家地区的游戏,需要登录该国的Apple Id才能在itunes里下载. 下面记录一下我注册日本地区的Apple Id过 ...

  3. uGUI练习(五) Draggable Object

    练习目标 学习制作一个可拖动的UI 一.步骤 监听UI的Drag事件,需要我们写一点点的代码. 1.创建一个Panel ,设置size为(100,100) 2.创建DraggableObjectSce ...

  4. java7-3 继承

    1.继承概述: 把多个类中相同的内容给提取出来定义到一个类中. 如何实现继承呢? Java提供了关键字:extends 格式: class 子类名 extends 父类名 {} 父类也称为基类.超类: ...

  5. C++ c++与C语言的区别(实用性增强,register关键字增强,全局变量检测增强)

    //区别①:实用性增强 #include<iostream> using namespace std; //C语言中的变量都必须在作用域开始的位置定义!! //C++中更强调语言的“实用性 ...

  6. Microsoft Visual Studio 正忙

    简介:Microsoft Visual Studio 正忙,Microsoft Visual Studio 正在等待内部操作完成.如果经常在正常使用的情况下遇到此延迟, 请向Microsoft报告此情 ...

  7. IOS开发之——登录加密也许用到的,反转字符串

    - (NSString *)stringByReversed{//    NSMutableString *s = [NSMutableString string];//    for (NSUInt ...

  8. error C2065: “CMainFrame”: 未声明的标识符

    xxxView.cp的开头包含 框架的头文件即可 : #include "MainFrm.h"

  9. .tostring()格式化大全

    C 货币 2.5.ToString("C") ¥2.50 D 十进制数 25.ToString("D5") 00025 E 科学型 25000.ToString ...

  10. mod mono xsp

    Mod_Mono 是Apache的一个扩展模块,使得apache支持asp.net. 该模块传递asp.net的请求到一个额外的程序 mod-mono-server(该程序是在安装xsp的时候自动安装 ...