2668: [cqoi2012]交换棋子

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 1112  Solved: 409
[Submit][Status][Discuss]

Description

有一个nm列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态。要求第i行第j列的格子只能参与mi,j次交换。

Input

第一行包含两个整数nm(1<=nm<=20)。以下n行为初始状态,每行为一个包含m个字符的01串,其中0表示黑色棋子,1表示白色棋子。以下n行为目标状态,格式同初始状态。以下n行每行为一个包含m个0~9数字的字符串,表示每个格子参与交换的次数上限。
 

Output

输出仅一行,为最小交换总次数。如果无解,输出-1。

Sample Input

3 3
110
000
001
000
110
100
222
222
222

Sample Output

4

HINT

 

Source

 

[Submit][Status][Discuss]

对于每一个格子,拆成三个点,分别为x,y,z。

其中,x为格子间转移边的入点,z为出点,y为与S和T的连接点。

S向每个原图中黑色,新图中白色的y点连一条容量为1,费用为0的边,流过这条边表示把该棋子换走替代其他棋子。

T向每个原图中白色,新图中黑色的y点连一条容量为1,费用为0的边,流经这条边表示用其他棋子把该棋子换走。

所有原图中黑色,新图中白色的点,x向y连容量为$\frac{limit_{i,j}}{2}$,费用为0的边,表示至多接受这么多替换;y向z连容量为$\frac{limit_{i,j}+1}{2}$,费用为0的边,表示之多提供这么多替换。所有原图中黑色,新图中白色的点,和这个反着连。新图原图中一样的,容量则都是$\frac{limit_{i,j}}{2}$。

按照八联通,所有相邻点对,连接其对应为x,z即可,容量无限,费用为1,表示交换一次的代价为1。

 #include <bits/stdc++.h>
#define rep(a,b,c) for(register int a=b;a<=c;++a)
const int mxn = , siz = , inf = 1e9, mv[][] = {{,},{,},{,},{,-}};
char a[mxn][mxn], b[mxn][mxn], c[mxn][mxn];
int n, m, d[mxn][mxn], id[mxn][mxn][], ID, cnt0, cnt1;
int s, t, tot, hd[siz], to[siz], nt[siz], fl[siz], vl[siz], dis[siz], pre[siz], que[siz], inq[siz], cost;
inline bool legal(int x, int y) { return x >= && x <= n && y >= && y <= m; }
inline void add(int u, int v, int f, int w) {
nt[tot] = hd[u]; to[tot] = v; fl[tot] = f; vl[tot] = +w; hd[u] = tot++;
nt[tot] = hd[v]; to[tot] = u; fl[tot] = ; vl[tot] = -w; hd[v] = tot++;
}
inline bool spfa(void) {
register int head = , tail = ;
rep(i, s, t)dis[i] = inf, inq[i] = ;
dis[que[tail++] = s] = , inq[s] = , pre[s] = -;
while (head != tail) {
int u = que[head++], v, i; inq[u] = ;
for (i = hd[u]; ~i; i = nt[i])if (fl[i] && dis[v = to[i]] > dis[u] + vl[i]) {
dis[v] = dis[u] + vl[i], pre[v] = i^; if (!inq[v])inq[que[tail++] = v] = ;
}
}
return dis[t] < inf;
}
inline int maxFlow(void) {
int ret = ;
while (spfa()) {
int flow = inf, i;
for (i = pre[t]; ~i; i = pre[to[i]])if (flow > fl[i^])flow = fl[i^];
for (i = pre[t]; ~i; i = pre[to[i]])fl[i] += flow, fl[i^] -= flow;
ret += flow, cost += flow * dis[t];
}
return ret;
}
signed main(void) {
scanf("%d%d", &n, &m);
s = , t = n * m * + ;
memset(hd, -, sizeof(hd));
rep(i, , n)scanf("%s", a[i] + );
rep(i, , n)scanf("%s", b[i] + );
rep(i, , n)scanf("%s", c[i] + );
rep(i, , n)rep(j, , m)d[i][j] = c[i][j] - '';
rep(i, , n)rep(j, , m)rep(k, , )id[i][j][k] = ++ID;
rep(i, , n)rep(j, , m) {
if (a[i][j] == '' && b[i][j] == '')
add(s, id[i][j][], , ), ++cnt0,
add(id[i][j][], id[i][j][], d[i][j] >> , ),
add(id[i][j][], id[i][j][], (d[i][j] + ) >> , );
if (a[i][j] == '' && b[i][j] == '')
add(id[i][j][], t, , ), ++cnt1,
add(id[i][j][], id[i][j][], (d[i][j] + ) >> , ),
add(id[i][j][], id[i][j][], d[i][j] >> , );
if (a[i][j] == b[i][j])
add(id[i][j][], id[i][j][], d[i][j] >> , ),
add(id[i][j][], id[i][j][], d[i][j] >> , );
}
rep(i, , n)rep(j, , m)rep(k, , )if (legal(i + mv[k][], j + mv[k][]))
add(id[i][j][], id[i + mv[k][]][j + mv[k][]][], inf, ),
add(id[i + mv[k][]][j + mv[k][]][], id[i][j][], inf, );
printf("%d\n", cnt0 == cnt1 && cnt0 == maxFlow() ? cost : -);
}

@Author: YouSiki

BZOJ 2668: [cqoi2012]交换棋子的更多相关文章

  1. BZOJ 2668 [cqoi2012]交换棋子 | 最小费用最大流

    传送门 BZOJ 2668 题解 同时分别限制流入和流出次数,所以把一个点拆成三个:入点in(x).中间点mi(x).出点ou(x). 如果一个格子x在初始状态是黑点,则连(S, mi(x), 1, ...

  2. BZOJ.2668.[CQOI2012]交换棋子(费用流zkw)

    题目链接 首先黑白棋子的交换等价于黑棋子在白格子图上移动,都到达指定位置. 在这假设我们知道这题用网络流做. 那么黑棋到指定位置就是一条路径,考虑怎么用流模拟出这条路径. 我们发现除了路径的起点和终点 ...

  3. 2668: [cqoi2012]交换棋子

    Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列的格子只能参与mi,j次交换. Input 第一行 ...

  4. BZOJ2668: [cqoi2012]交换棋子

    题解: 可以戳这里:http://www.cnblogs.com/zig-zag/archive/2013/04/21/3033485.html 其实自己yy一下就知道这样建图的正确性了. 感觉太神奇 ...

  5. [cqoi2012]交换棋子

      2668: [cqoi2012]交换棋子 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1334  Solved: 518[Submit][Stat ...

  6. 【BZOJ2668】[cqoi2012]交换棋子 费用流

    [BZOJ2668][cqoi2012]交换棋子 Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列 ...

  7. 洛谷 P3159(BZOJ 2668)[CQOI2012]交换棋子

    有一个\(n\)行\(m\)列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第\(i\)行第\(j\)列的格子只能参与\(m[i][j]\)次交换 ...

  8. BZOJ2668:[CQOI2012]交换棋子——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=2668 https://www.luogu.org/problemnew/show/P3159#sub ...

  9. P3159 [CQOI2012]交换棋子

    思路 相当神奇的费用流拆点模型 最开始我想到把交换黑色棋子看成一个流流动的过程,流从一个节点流向另一个节点就是交换两个节点,然后把一个位置拆成两个点限制流量,然后就有了这样的建图方法 S向所有初始是黑 ...

随机推荐

  1. LintCode——尾部的零

    尾部的零:设计一个算法,计算出n阶乘中尾部零的个数 样例:11! = 39916800.因此应该返回2 分析:假如你把1 × 2 ×3× 4 ×……×N中每一个因数分解质因数,例如 1 × 2 × 3 ...

  2. 使用vs2015编译、部署ssd-caffe(weiliu89版,CPU模式)

    前因项目所需,须训练一个快速模型以实现目标物体的实时检测.历经多次实践,发现MobileNetSSD网络符合要求,故在本人工作PC上部署weiliu89版本的ssd-caffe以期用之训练项目要求之模 ...

  3. SpringCloud使用Feign出现java.lang.ClassNotFoundException: org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory异常

    废话不多说!!! 在SpringCloud项目中配置了Feign来调用restful接口,项目启动的时候报错,报错信息如下: 找不到org.springframework.cloud.client.l ...

  4. NO--15 微信小程序,scroll-view选项卡和跳转

    大多数的商城类小程序都有这个功能,点击“全部订单”,“待付款”,“待发货”,“待收货”,“已完成”,会跳转页面且跳至与之相对应的选项卡中.所以我们在开发该小程序时也做了相同的功能.如下图:   scr ...

  5. L2 Helios OPcodez

    天堂2 Helios太阳神版本 的客户端和服务端封包 *********************** Client ***********************00 SendLogOut01 Req ...

  6. CentOS 7 Docker基本特性

    Docker是一个开源的应用容器引擎,开发人员可以非常容易地打包已经开发好的应用,同时将应用相关的依赖包也打包到这样一个可移植的容器中,然后发布到任意的Linux主机系统上.Docker是基于Linu ...

  7. kali vmtools 不能复制粘贴解决方法(绝对实用)

    朋友问起怎么vm kali 2019怎么不能复制了,而且网上的方法大多不适合.我就在这儿记录一笔吧,方便大家. 之前发现最新kali复制粘贴不能用,后来发现一个奇妙的套路,不是共享文件夹.只需要把文件 ...

  8. 前端_CSS

    目录 CSS语法 CSS的四种引入方式 CSS选择器 CSS属性操作 补充 示例(一些小模板) CSS语法 CSS 规则由两个主要的部分构成:选择器,以及一条或多条声明. 1 2 3 4 5 6 7 ...

  9. Django_分页

    目录 基本语法 示例 示例1 使用django内置Paginator模块 示例2 改写Paginator 示例3 自定义pager组件 示例3.1 objs与pager各自单独使用 示例3.2 obj ...

  10. 基于NABCD评论作业-王者荣耀交流协会PSP DAILY

    一.根据(不限于)NABCD评论作品的选题   N(Need,需求):在我知道PSP DAILY这款软件的时候,就认为这款软件对于学习软件工程课的学生来说有很大的需要.对于需求来说,软件工程课程中的学 ...