bzoj 2756奇怪的游戏
2756: [SCOI2012]奇怪的游戏
Time Limit: 40 Sec Memory Limit: 128 MB
Description
Blinke 最近喜欢上一个奇怪的游戏。 这个游戏在一个 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
题解
首先,我们可以很明显的看出最后形成的数\(x\)一定具有单调性,所以我们可以二分\(x\)。
那么如何写\(check(x)\)呢?
首先我们可以将棋盘黑白染色,之后再将黑色与\(T\)相连,将白色与\(S\)相连,再将黑白色之间连接。这样就可以用一个最大流来解决。
因为每个数字都要变为\(x\),所以可以将节点与\(S\)或\(T\)相连的边权设为\(x-val\),之后我们可以将黑白棋子之间的边权设为\(inf\)(其实边权值可以算出,不过由于之前已经限制了边权,所以这里可以不用处理边权)。
因为这个最大流其实就是加了多少次,所以最大流应该等于所有数字与x之差之和的一半。这样,我们就可以写出\(check\)了。
另外,因为\(Cnt[0]*x - Sum[0]=Cnt[1]*x - Sum[1]\),\(Cnt\)表示黑白棋格的个数,\(Sum\)表示黑白棋格各自的和,所以当\(Cnt[0] \neq Cnt[1]\)时,我们可以直接得出\(x\),之后直接\(check(x)\)就好了。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MS = 100000, N = 42;
const LL inl = 1LL << 55;
int ina; char inc, inb[1<<16], *ins = inb, *ine = inb; bool insign;
inline char getc() {
if (ins == ine) ine = (ins = inb) + fread(inb, 1, 1 << 16, stdin);
return (ins == ine) ? EOF : *ins++;
}
inline int geti() {
insign = false;
while ((inc = getc()) < '0' || inc > '9') insign |= inc == '-'; ina = inc - '0';
while ((inc = getc()) >= '0' && inc <= '9') ina = (ina << 3) + (ina << 1) + inc - '0';
return insign ? -ina : ina;
}
int mp[N][N], n, m;
bool col[N][N];
LL Sum[2], Num[2], mv;
namespace CC {
int To[MS], Nxt[MS], totE, head[N * N], S, T, d[N * N], dt[N * N];
LL C[MS];
inline void Adde(int a, int b, LL c) {
To[totE] = b; Nxt[totE] = head[a]; C[totE] = c; head[a] = totE++;
To[totE] = a; Nxt[totE] = head[b]; C[totE] = 0; head[b] = totE++;
}
const int dx[] = {0,0,-1,1};
const int dy[] = {1,-1,0,0};
inline int getp(const int &x, const int &y) { return (x-1)*m + y; }
LL dfs(int u, LL flow) {
if (u==T||!flow) return flow;
LL res = 0, t;
for (int i = head[u]; ~i; i = Nxt[i])
if (d[u] == d[To[i]] + 1 && C[i] > 0){
t = dfs(To[i], min(flow, C[i]));
C[i] -= t, C[i^1] += t;
res += t, flow -= t;
if (!flow) return res;
if (d[S] > T) return res;
}
if (!(--dt[d[u]])) d[S] = T + 1;
++dt[++d[u]];
return res;
}
bool check(LL x) {
memset(head, -1, sizeof head); totE = 0;
S = 0, T = getp(n, m) + 1;
LL t, tot = 0, maxflow = 0;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j) {
t = x - mp[i][j];
if (col[i][j]) Adde(getp(i, j), T, t);
else Adde(S, getp(i, j), t);
tot += t;
}
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
for (int k = 0; k < 4; ++k) {
int _i = i + dx[k], _j = j + dy[k];
if (_i < 1 || _i > n || _j < 1 || _j > m) continue;
if (!col[i][j]) Adde(getp(i, j), getp(_i, _j), inl);
}
memset(d, 0, sizeof d); memset(dt, 0, sizeof dt);
dt[0] = T + 1;
while (d[S] < T + 1) maxflow += dfs(S, inl);
return tot == (maxflow << 1);
}
}
void init() {
memset(col, 0, sizeof col);
n = geti(), m = geti();
*Sum = Sum[1] = *Num = Num[1] = mv = 0LL;
bool st = true;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j) {
if ((mp[i][j] = geti()) > mv) mv = mp[i][j];
col[i][j] = !col[i][j-1];
if (j <= 1) col[i][j] = (st = !st);
++Num[col[i][j]]; Sum[col[i][j]] += mp[i][j];
}
}
#define getskip(a) (a*n*m - Sum[0] - Sum[1]) >> 1
void Work() {
if (n * m & 1) {
LL x = Sum[0] - Sum[1];
if (x >= mv && CC::check(x)) printf("%lld\n", getskip(x));
else puts("-1");
} else {
LL l = mv, r = inl / 1000, M, ans = -1;
while (l <= r) {
M = l + r >> 1;
if (CC::check(M)) r = (ans = M) - 1;
else l = M + 1;
}
if (~ans) printf("%lld\n", getskip(ans));
else puts("-1");
}
}
int main() {
for (int T = geti(); T; --T) {
init(); Work();
}
return 0;
}
bzoj 2756奇怪的游戏的更多相关文章
- [BZOJ 2756] 奇怪的游戏
Link:https://www.lydsy.com/JudgeOnline/problem.php?id=2756 Algorithm: 比较新颖的题目 首先发现是对矩阵中相邻两数进行操作 & ...
- BZOJ 2756 奇怪的游戏(最大流)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2756 题意:在一个 N*M 的棋盘上玩,每个格子有一个数.每次 选择两个相邻的格子,并使 ...
- 【BZOJ】【2756】【SCOI2012】奇怪的游戏
网络流-最大流 这题……建模部分先略过 这道题是会卡时限的T_T俺的Dinic被卡了,在此放几篇很棒的讲网络流算法的文章,至于大家耳熟能详的论文就不放了…… http://www.cppblog.co ...
- BZOJ 2756: [SCOI2012]奇怪的游戏 [最大流 二分]
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3352 Solved: 919[Submit][Stat ...
- BZOJ 2756: [SCOI2012]奇怪的游戏 网络流/二分
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 1594 Solved: 396[Submit][Stat ...
- BZOJ 2756 SCOI2012 奇怪的游戏 最大流
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2756 Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N ...
- bzoj 2756 [SCOI2012]奇怪的游戏 二分+网络流
2756:[SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 4926 Solved: 1362[Submit][Stat ...
- bzoj 2756: [SCOI2012]奇怪的游戏
Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻 的格子,并使这两个数都加上 1. 现在 B ...
- BZOJ 2756 【SCOI2012】 奇怪的游戏
题目链接:奇怪的游戏 一开始这道题想岔了……想到黑白染色后对总格子数按奇偶性分类讨论,然后没发现奇数个格子的可以直接解方程…… 首先可以发现每次操作是给相邻的两个格子权值加一,因此我们把棋盘黑白染色后 ...
随机推荐
- OracleHelper类
using System; using System.Collections; using System.Collections.Generic; using System.Data; using S ...
- C、C++: 引用、指针、实例、内存模型、namespace
// HelloWorld.cpp : Defines the entry point for the console application. // #include "stdafx.h& ...
- 阿里云centos安装svn和submin
概述 没有找到可以让团队方便使用的云盘,暂时搭建一个svn凑合用一下 svn有三种安装方式 安装方式 服务程序 服务协议 用户和密码 授权 系统配置 svn独立安装 svnserve svn pass ...
- Centos允许root远程登录设置
以root权限执行 vi /etc/ssh/sshd_config 将 #PermitRootLogin yes 这一行的“#”去掉,修改为: PermitRootLogin yes 重启ssh服 ...
- Visual Studio SetSite failed for package [JavaScriptWebExtensionsPackage] 错误解决方案一则
安装 AspNet5.ENU.RC1.exe Microsoft ASP.NET and Web Tools 2015 (RC) – Visual Studio 2015 打开VS后发生了错误 < ...
- 关于mysql数据库插入数据,不能插入中文和出现中文乱码问题
首先,推荐一篇博客:http://www.cnblogs.com/sunzn/archive/2013/03/14/2960248.html 当时,我安装完mysql数据库后,新建一个数据库后插入数据 ...
- VIM 常用命令
1.当vi打开时默认为命令模式,要转入输入模式,需要按a或者i键. 命令模式下: :wq 保存并且退出 :w 只保存不推出 :q 不保存退出 :q! 不保存强制退出 :wq! 保存并强制退 ...
- Qt 之 入门例程 (一)
以 “Hello Qt” 为例,介绍如何建立一个 Qt 工程 . 1 QLabel 例程 QLabel 继承自 QFrame (继承自 QWidget),主要用来显示文本和图片. 1.1 Hell ...
- UVALive3902 Network[贪心 DFS&&BFS]
UVALive - 3902 Network Consider a tree network with n nodes where the internal nodes correspond to s ...
- Java集合之泛型的使用
Java集合之泛型的使用 泛型提供了一种轻便灵活的数据操作,数据的安全性相对提高. 泛型提供了对列表元素的约束条件,比如ArrayList有序链表,可存储任意类型的元素. 此处构建一个ArrayLis ...