[luoguP3159] [CQOI2012]交换棋子(最小费用最大流)
好难的网络流啊,建图真的超难。
如果不告诉我是网络流的话,我估计就会写dfs了。
使用费用流解决本题,设点 $p[i][j]$ 的参与交换的次数上限为 $v[i][j]$ ,以下为建图方式:
将一个点分成三个点,分别为入点,原点和出点。
如果开始的图上该位置有棋子,那么从S到该点的原点连一条边权1,费用0的边
如果结束的图上该位置有棋子,那么从该点的原点到T连一条边权1,费用0的边
如果该点只在开始的图上出现,那么从该点的入点向原点连一条边权为 $v[i][j]/2$ ,费用为1的边,从该点的原点向出点连一条边权为 $(v[i][j]+1)/2$ ,费用为0的边
如果该点只在结束的图上出现,那么从该点的入点向原点连一条边权为 $(v[i][j]+1)/2$ ,费用为1的边,从该点的原点向出点连一条边权为 $v[i][j]/2$ ,费用为0的边
如果以上两点都不符合,那么从该点的入点向原点连一条边权为 $v[i][j]/2$ ,费用为1的边,从该点的原点向出点连一条边权为 $v[i][j]/2$ ,费用为0的边
——by zhouyonglong
我只是题解的搬运工。
最后把每个点的原点和它相邻的点的原点连一条容量为INF,费用为0的边
- #include <queue>
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- #define N 1000001
- #define id(i, j, k) ((i - 1) * m + j + (k - 1) * n * m)
- using namespace std;
- int n, m, cnt, s, t, ans, sum1, sum2, sum;
- int head[N], to[N], nex[N], val[N], cost[N], dis[N], pre[N], path[N];
- char s1[21][21], s2[21][21], c[21][21];
- const int dx[8] = {1, 1, 0, -1, -1, -1, 0, 1}, dy[8] = {0, 1, 1, 1, 0, -1, -1, -1};
- bool vis[N];
- inline int read()
- {
- int x = 0, f = 1;
- char ch = getchar();
- for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
- for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
- return x * f;
- }
- inline void add(int x, int y, int z, int v)
- {
- to[cnt] = y;
- val[cnt] = z;
- cost[cnt] = v;
- nex[cnt] = head[x];
- head[x] = cnt++;
- }
- inline bool spfa()
- {
- int i, u, v;
- queue <int> q;
- memset(vis, 0, sizeof(vis));
- memset(pre, -1, sizeof(pre));
- memset(dis, 127, sizeof(dis));
- q.push(s);
- dis[s] = 0;
- while(!q.empty())
- {
- u = q.front();
- vis[u] = 0;
- q.pop();
- for(i = head[u]; ~i; i = nex[i])
- {
- v = to[i];
- if(val[i] && dis[v] > dis[u] + cost[i])
- {
- dis[v] = dis[u] + cost[i];
- pre[v] = u;
- path[v] = i;
- if(!vis[v])
- {
- q.push(v);
- vis[v] = 1;
- }
- }
- }
- }
- return pre[t] != -1;
- }
- inline void E()
- {
- puts("-1"), exit(0);
- }
- int main()
- {
- int i, j, k, x, y, f;
- n = read();
- m = read();
- s = 0, t = 3 * n * m + 1;
- memset(head, -1, sizeof(head));
- for(i = 1; i <= n; i++) scanf("%s", s1[i] + 1);
- for(i = 1; i <= n; i++) scanf("%s", s2[i] + 1);
- for(i = 1; i <= n; i++) scanf("%s", c[i] + 1);
- for(i = 1; i <= n; i++)
- for(j = 1; j <= m; j++)
- {
- c[i][j] -= '0';
- if(s1[i][j] == '1')
- {
- sum1++;
- add(s, id(i, j, 2), 1, 0);
- add(id(i, j, 2), s, 0, 0);
- }
- if(s2[i][j] == '1')
- {
- sum2++;
- add(id(i, j, 2), t, 1, 0);
- add(t, id(i, j, 2), 0, 0);
- }
- if(s1[i][j] == '1' && s2[i][j] == '0')
- {
- add(id(i, j, 1), id(i, j, 2), c[i][j] / 2, 1);
- add(id(i, j, 2), id(i, j, 1), 0, -1);
- add(id(i, j, 2), id(i, j, 3), (c[i][j] + 1) / 2, 0);
- add(id(i, j, 3), id(i, j, 2), 0, 0);
- }
- if(s1[i][j] == '0' && s2[i][j] == '1')
- {
- add(id(i, j, 1), id(i, j, 2), (c[i][j] + 1) / 2, 1);
- add(id(i, j, 2), id(i, j, 1), 0, -1);
- add(id(i, j, 2), id(i, j, 3), c[i][j] / 2, 0);
- add(id(i, j, 3), id(i, j, 2), 0, 0);
- }
- if(s1[i][j] == s2[i][j])
- {
- add(id(i, j, 1), id(i, j, 2), c[i][j] / 2, 1);
- add(id(i, j, 2), id(i, j, 1), 0, -1);
- add(id(i, j, 2), id(i, j, 3), c[i][j] / 2, 0);
- add(id(i, j, 3), id(i, j, 2), 0, 0);
- }
- for(k = 0; k < 8; k++)
- {
- x = i + dx[k];
- y = j + dy[k];
- if(1 <= x && x <= n && 1 <= y && y <= m)
- {
- add(id(i, j, 3), id(x, y, 1), 1e9, 0);
- add(id(x, y, 1), id(i, j, 3), 0, 0);
- }
- }
- }
- if(sum1 != sum2) E();
- while(spfa())
- {
- f = 1e9;
- for(i = t; i != s; i = pre[i]) f = min(f, val[path[i]]);
- sum += f;
- ans += dis[t];
- for(i = t; i != s; i = pre[i])
- {
- val[path[i]] -= f;
- val[path[i] ^ 1] += f;
- }
- }
- if(sum != sum1) E();
- printf("%d\n", ans);
- return 0;
- }
[luoguP3159] [CQOI2012]交换棋子(最小费用最大流)的更多相关文章
- BZOJ 2668 [cqoi2012]交换棋子 | 最小费用最大流
传送门 BZOJ 2668 题解 同时分别限制流入和流出次数,所以把一个点拆成三个:入点in(x).中间点mi(x).出点ou(x). 如果一个格子x在初始状态是黑点,则连(S, mi(x), 1, ...
- 【BZOJ-2668】交换棋子 最小费用最大流
2668: [cqoi2012]交换棋子 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1055 Solved: 388[Submit][Status ...
- BZOJ2668:[CQOI2012]交换棋子(费用流)
题目描述 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列的格子只能参与mi,j次交换. 输入输出格式 输入格式: 第一行 ...
- BZOJ2668 [cqoi2012]交换棋子 【费用流】
题目链接 BZOJ2668 题解 容易想到由\(S\)向初始的黑点连边,由终态的黑点向\(T\)连边,然后相邻的点间连边 但是这样满足不了交换次数的限制,也无法计算答案 考虑如何满足一个点的交换次数限 ...
- [CQOI2012] 交换棋子 (费用流)
$pdf\space solution$ link #include<iostream> #include<cstring> #include<cstdio> ...
- 【BZOJ2668】[cqoi2012]交换棋子 费用流
[BZOJ2668][cqoi2012]交换棋子 Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列 ...
- [cqoi2012]交换棋子
2668: [cqoi2012]交换棋子 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1334 Solved: 518[Submit][Stat ...
- BZOJ 2668: [cqoi2012]交换棋子
2668: [cqoi2012]交换棋子 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1112 Solved: 409[Submit][Status ...
- [bzoj2668] [洛谷P3159] [cqoi2012] 交换棋子
Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列的格子只能参与mi,j次交换. Input 第一行 ...
随机推荐
- JS判断两个对象相同属性的属性值是否相等
function isObjectValueEqual(a, b) { var aProps = Object.getOwnPropertyNames(a); var bProps = Object. ...
- siege4安装和使用介绍
使用文档参考地址:https://www.joedog.org/siege-manual/ siege4地址:http://download.joedog.org/siege/ cd /usr/loc ...
- React学习实例总结,包含yeoman安装、webpack构建
1.安装yeoman 在安装nodeJs的基础上,输入命令:npm install -g yo grunt-cli bower,安装yeoman,grunt,bowerify 安装完成后,输入命令:y ...
- python_113_socket编程
Socket语法及相关 socket概念 socket本质上就是在2台网络互通的电脑之间,架设一个通道,两台电脑通过这个通道来实现数据的互相传递. 我们知道网络 通信 都 是基于 ip+port 方能 ...
- 一张图看懂苹果MacBook所有屏幕分辨率
苹果全新12寸超薄MacBook比曾经最薄的MacBook Air更薄,不过却配备了Retina视网膜显示屏.12英寸RetinaMacBook上的显示屏分辨率为2304*1440,虽然不如15寸和1 ...
- BOM函数之history对象
前面的话 history对象保存着用户上网的历史记录,从窗口被打开的那一刻算起.由于安全方面的考虑,开发人员无法得到用户浏览器的URL,但借由用户访问过的页面列表,可以在不知道实际URL的情况下实现后 ...
- Ibatis入门基本语法
1. Ibatis是开源软件组织Apache推出的一种轻量级的对象关系映射(ORM)框架,和Hibernate.Toplink等在java编程的对象持久化方面深受开发人员欢迎. 对象关系映 ...
- Luogu P2397 yyy loves Maths VI (mode)
题目传送门 虽然只是一道黄题,但还是学到了一点新知识-- 摩尔投票法 用\(O(1)\)的内存,\(O(n)\)的时间来找出一串长度为n的数中的众数,前提是众数出现的次数要大于\(n/2\) 方法很简 ...
- shell脚本,锁机制
[root@localhost wyb]# cat suijizhi.sh #!/bin/bash a=`|grep -v grep |wc -l` echo "$a" [ $a ...
- easyUI 之datagrid 在前端自定义排序
首先先来看一下,直接从后台读取数据并展示到前端的列表,后端传回的数据是“按商品ID倒序排列” 前端源代码 $('#good_tables').datagrid({ nowrap: true, auto ...