luogu3159 [CQOI2012]交换棋子
把每个点拆成 x y z
对于第 i 个点,x->y是表示流入的,y->z是表示流出的。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
int n, m, ss, tt, hea[1305], cnt, minCost, pre[1305], dis[1305], maxFlow, qaq, qwq;
const int oo=0x3f3f3f3f;
const int dx[]={0, 1, 1, 1, 0, -1, -1, -1, 0};
const int dy[]={0, 1, 0, -1, -1, -1, 0, 1, 1};
bool vis[1305];
char cs[25][25], js[25][25], xz[25][25];
struct Edge{
int too, nxt, val, cst;
}edge[9005];
queue<int> d;
int x(int i, int j){
return (i-1)*m+j;
}
int y(int i, int j){
return (i-1)*m+j+n*m;
}
int z(int i, int j){
return (i-1)*m+j+2*n*m;
}
void add_edge(int fro, int too, int val, int cst){
edge[cnt].nxt = hea[fro];
edge[cnt].too = too;
edge[cnt].val = val;;
edge[cnt].cst = cst;
hea[fro] = cnt++;
}
void addEdge(int fro, int too, int val, int cst){
add_edge(fro, too, val, cst);
add_edge(too, fro, 0, -cst);
}
int bfs(){
memset(dis, 0x3f, sizeof(dis));
memset(pre, -1, sizeof(pre));
dis[ss] = 0;
vis[ss] = true;
d.push(ss);
while(!d.empty()){
int x=d.front();
d.pop();
vis[x] = false;
for(int i=hea[x]; i!=-1; i=edge[i].nxt){
int t=edge[i].too;
if(dis[t]>dis[x]+edge[i].cst && edge[i].val>0){
dis[t] = dis[x] + edge[i].cst;
pre[t] = i;
if(!vis[t]){
vis[t] = true;
d.push(t);
}
}
}
}
return dis[tt]!=oo;
}
void dinic(){
while(bfs()){
int tmp=oo;
for(int i=pre[tt]; i!=-1; i=pre[edge[i^1].too])
tmp = min(tmp, edge[i].val);
for(int i=pre[tt]; i!=-1; i=pre[edge[i^1].too]){
edge[i].val -= tmp;
edge[i^1].val += tmp;
minCost += tmp * edge[i].cst;
}
maxFlow += tmp;
}
}
int main(){
memset(hea, -1, sizeof(hea));
cin>>n>>m;
for(int i=1; i<=n; i++) scanf("%s", cs[i]+1);
for(int i=1; i<=n; i++) scanf("%s", js[i]+1);
for(int i=1; i<=n; i++) scanf("%s", xz[i]+1);
ss = 0; tt = n * m * 3 + 1;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++){
if(cs[i][j]=='1' && js[i][j]=='0'){
qaq++;
addEdge(ss, y(i,j), 1, 0);
addEdge(x(i,j), y(i,j), (xz[i][j]-'0')/2, 0);
addEdge(y(i,j), z(i,j), (xz[i][j]-'0'+1)/2, 0);//原来黑而后来白,给流出的分多一点容量比较好
}
else if(cs[i][j]=='0' && js[i][j]=='1'){
qwq++;
addEdge(y(i,j), tt, 1, 0);
addEdge(x(i,j), y(i,j), (xz[i][j]-'0'+1)/2, 0);
addEdge(y(i,j), z(i,j), (xz[i][j]-'0')/2, 0);
}
else{
addEdge(x(i,j), y(i,j), (xz[i][j]-'0')/2, 0);
addEdge(y(i,j), z(i,j), (xz[i][j]-'0')/2, 0);
}
for(int k=1; k<=8; k++){
int kx=i+dx[k];
int ky=j+dy[k];
if(kx<1 || kx>n || ky<1 || ky>m) continue;
addEdge(z(i,j), x(kx,ky), oo, 1);
}
}
dinic();
if(qaq==qwq && maxFlow==qwq) cout<<minCost<<endl;
else cout<<"-1"<<endl;
return 0;
}
luogu3159 [CQOI2012]交换棋子的更多相关文章
- BZOJ2668: [cqoi2012]交换棋子
题解: 可以戳这里:http://www.cnblogs.com/zig-zag/archive/2013/04/21/3033485.html 其实自己yy一下就知道这样建图的正确性了. 感觉太神奇 ...
- BZOJ 2668: [cqoi2012]交换棋子
2668: [cqoi2012]交换棋子 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1112 Solved: 409[Submit][Status ...
- 【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 ...
- 洛谷 P3159(BZOJ 2668)[CQOI2012]交换棋子
有一个\(n\)行\(m\)列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第\(i\)行第\(j\)列的格子只能参与\(m[i][j]\)次交换 ...
- P3159 [CQOI2012]交换棋子
思路 相当神奇的费用流拆点模型 最开始我想到把交换黑色棋子看成一个流流动的过程,流从一个节点流向另一个节点就是交换两个节点,然后把一个位置拆成两个点限制流量,然后就有了这样的建图方法 S向所有初始是黑 ...
- BZOJ.2668.[CQOI2012]交换棋子(费用流zkw)
题目链接 首先黑白棋子的交换等价于黑棋子在白格子图上移动,都到达指定位置. 在这假设我们知道这题用网络流做. 那么黑棋到指定位置就是一条路径,考虑怎么用流模拟出这条路径. 我们发现除了路径的起点和终点 ...
- 2668: [cqoi2012]交换棋子
Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列的格子只能参与mi,j次交换. Input 第一行 ...
- [CQOI2012]交换棋子 网络流
---题面--- 题解: 一开始很快想出了一个接近正解的建图方法,但其实是错误的,不过还是骗了70分_(:зゝ∠)_ 首先我们可以观察到棋子有限,但费用多种,其实也就相当于限制了流量,找最小费用 对于 ...
随机推荐
- [译]Understanding ECMAScript6 函数
函数 函数是任何编程语言的重要组成部分,而自从JavaScript被引入以来,JavaScript的函数就未有太多改变.遗留下来的积压问题及微妙行为使我们很容易犯错误,或者需要更多的代码来实现一个非常 ...
- Gin框架body参数获取
需求: 记录所有请求的json数据 body, _ := ioutil.ReadAll(c.Request.Body) if body != nil { log.Info("请求body内容 ...
- hdu6376 度度熊剪纸条
思路: 01背包.有些细节需要注意一下,比如k = 0的情况. 实现: #include <bits/stdc++.h> using namespace std; typedef pair ...
- 重置Cacti密码
Cacti登录密码忘记,重置Cacti密码 用root用户进入系统 [root@localhsot]# mysql -u root -p mysql> show databases; mysql ...
- web前端性能优化 (share)
本文转自:http://www.cnblogs.com/50614090/archive/2011/08/19/2145620.html 一. WEB前台的优化规则 一.尽量减少 HTTP 请求 有几 ...
- COGS 2082. Asm.Def谈笑风生
★ 输入文件:asm_talk.in 输出文件:asm_talk.out 简单对比时间限制:2 s 内存限制:256 MB [题目描述] “人呐都不知道,自己不可以预料,直升机刚一出圣 ...
- ubuntu 16.0 利用ant编译 hadoop-eclipse-plugins2.6.0
折腾了两天,抱着不放弃的精神,我终于编译出我自己所需的hadoop中在eclipse中的插件 在网上下载的可能因为版本不一致,在编译的时候出现各种各样的问题,包括你的eclipse版本和hadoop版 ...
- ConCurrent in Practice小记 (4)
ConCurrent in Practice小记 (4) Executors Callable && Future <T> Callable:此接口有一个call()方法. ...
- iterator与iterable
用Iterator模式实现遍历集合Iterator模式是用于遍历集合类的标准访问方法.它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构.例如,如果没有使用Iterato ...
- Luogu P5352 Terrible Homework
神仙@TheLostWeak出的题,因为他最近没时间所以我先写一下sol(其实我也没什么时间) 作为一道简单的数据结构题想必大家都能看出必须用LCT维护信息吧 一个朴素的想法就是直接维护四种操作的值, ...