【题解】CQOI2012交换棋子
感受到网络流的强大了……这道题目的关键在于:
前后颜色不变的,流入流出的次数相等;原本是黑色的最后变成了白色,流出比流入次数多1;原本是白色最后变成黑色,流入比流出次数多一。所以我们将每一点拆成3个点,分别代表流入点,原点与流出点。最开始为黑色的点与源点连流量为1,费用为0的边,最后为黑色的点与汇点连流量为1,费用为0的边。
#include<bits/stdc++.h>
using namespace std;
#define maxn 300
#define maxm 8000
#define INF 99999
int n, m, size, tem, a[maxn][maxn], b[maxn][maxn], c[maxn][maxn], head[maxm];
int cnp, fans, ans, cost, dis[maxm], pre[maxm], flow[maxm];
int dx[] = {, , , , , , -, -, -};
int dy[] = {, , -, , , -, , , -};
int s = , t;
bool vis[maxm];
deque <int> q; struct edge
{
int to, last, f, c;
}E[maxn * ]; void add(int u, int v, int f, int c)
{
E[cnp].to = v, E[cnp].last = head[u], E[cnp].f = f, E[cnp].c = c; head[u] = cnp ++;
E[cnp].to = u, E[cnp].last = head[v], E[cnp].f = , E[cnp].c = -c; head[v] = cnp ++;
} int Get_id(int x, int y)
{
return (x - ) * m + y;
} void init()
{
memset(head, -, sizeof(head));
} int SPFA()
{
q.push_back(s);
flow[s] = INF;
for(int i = ; i <= n * m * + ; i ++) dis[i] = INF;
while(!q.empty())
{
int u = q.front();
q.pop_front();
vis[u] = false;
for(int i = head[u]; i != -; i = E[i].last)
{
int v = E[i].to;
if(E[i].f && dis[v] > dis[u] + E[i].c)
{
dis[v] = dis[u] + E[i].c, pre[v] = i;
flow[v] = min(flow[u], E[i].f);
if(!vis[v])
{
vis[v] = true;
if(!q.empty() && dis[v] < dis[q.front()]) q.push_front(v);
else q.push_front(v);
}
}
}
}
if(dis[t] >= INF) return false;
else return true;
} void Max_flow()
{
while(SPFA())
{
int v = pre[t];
while()
{
E[v].f -= flow[t];
E[v ^ ].f += flow[t];
if(E[v ^ ].to == s) break;
v = pre[E[v ^ ].to];
}
ans += flow[t];
cost += flow[t] * dis[t];
}
} void Get_input()
{
for(int i = ; i <= n; i ++)
{
string s; cin >> s;
for(int j = ; j < m; j ++)
a[i][j + ] = s[j] - '';
}
for(int i = ; i <= n; i ++)
{
string s; cin >> s;
for(int j = ; j < m; j ++)
b[i][j + ] = s[j] - '';
}
for(int i = ; i <= n; i ++)
{
string s; cin >> s;
for(int j = ; j < m; j ++)
c[i][j + ] = s[j] - '';
}
} void Connect()
{
for(int i = ; i <= n; i ++)
for(int j = ; j <= m; j ++)
{
int u = Get_id(i, j);
if(a[i][j]) tem ++, add(s, u, , );
if(b[i][j]) fans ++, add(u, t, , );
if(a[i][j] == b[i][j])
{
add(u + size, u, c[i][j] / , );
add(u, u + * size, c[i][j] / , );
}
else if(b[i][j])
{
add(u + size, u, (c[i][j] + ) / , );
add(u, u + * size, c[i][j] / , );
}
else if(a[i][j])
{
add(u + size, u, c[i][j] / , );
add(u, u + * size, (c[i][j] + ) / , );
}
for(int k = ; k <= ; k ++)
{
int x = i + dx[k], y = j + dy[k];
if(x < || x > n || y < || y > m) continue;
add(u + * size, Get_id(x, y) + size, INF, );
}
}
} int main()
{
scanf("%d%d", &n, &m);
init();
t = n * m * + , size = n * m;
Get_input();
Connect();
if(tem != fans)
{
printf("-1\n");
return ;
}
Max_flow();
if(ans == fans) printf("%d", cost >> );
else printf("-1\n");
return ;
}
【题解】CQOI2012交换棋子的更多相关文章
- BZOJ2668: [cqoi2012]交换棋子
题解: 可以戳这里:http://www.cnblogs.com/zig-zag/archive/2013/04/21/3033485.html 其实自己yy一下就知道这样建图的正确性了. 感觉太神奇 ...
- 【BZOJ2668】[cqoi2012]交换棋子 费用流
[BZOJ2668][cqoi2012]交换棋子 Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列 ...
- BZOJ 2668: [cqoi2012]交换棋子
2668: [cqoi2012]交换棋子 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1112 Solved: 409[Submit][Status ...
- [cqoi2012]交换棋子
2668: [cqoi2012]交换棋子 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1334 Solved: 518[Submit][Stat ...
- BZOJ2668:[CQOI2012]交换棋子——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2668 https://www.luogu.org/problemnew/show/P3159#sub ...
- 洛谷 P3159(BZOJ 2668)[CQOI2012]交换棋子
有一个\(n\)行\(m\)列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第\(i\)行第\(j\)列的格子只能参与\(m[i][j]\)次交换 ...
- [CQOI2012]交换棋子 网络流
---题面--- 题解: 一开始很快想出了一个接近正解的建图方法,但其实是错误的,不过还是骗了70分_(:зゝ∠)_ 首先我们可以观察到棋子有限,但费用多种,其实也就相当于限制了流量,找最小费用 对于 ...
- BZOJ2668:[CQOI2012]交换棋子(费用流)
题目描述 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列的格子只能参与mi,j次交换. 输入输出格式 输入格式: 第一行 ...
- [luoguP3159] [CQOI2012]交换棋子(最小费用最大流)
传送门 好难的网络流啊,建图真的超难. 如果不告诉我是网络流的话,我估计就会写dfs了. 使用费用流解决本题,设点 $p[i][j]$ 的参与交换的次数上限为 $v[i][j]$ ,以下为建图方式: ...
随机推荐
- javaScript 字符串与unicode码之间的相互转换,函数的封装
在我们的开发过程中,有时在对数据进行储存的时候,我们需要将字符串转成unicode. 比如,在jsp开发时,前端使用页面间传值时,将传值参数先存入cookie中,然后在使用的时候,再从ookie中取出 ...
- 浅谈localStorage的用法
今天接到一个任务,说是让自动调节textarea标记的输入高度,而且还要记录下来,下次登录的时候还是调节后的高度,我第一时间就想到了localStorage的用法,直接代码献上: <html l ...
- Ubuntu设置代理服务器
由于公司网络的原因,apache的网站访问不了,对于需要经常访问apache网站查看文档的我,最近想了一种方法,在自己的阿里云服务器上搭建一个代理服务器.经过查资料,最终决定使用TinyProxy. ...
- 算法竞赛入门经典-1.5.4 Q&A
这小节考察实践能力,要求在不要查书.不要网上找答案,自己用实验的方法解决以下五个问题: 做这五道题时,好几道都没思路,违反了规则到网上找了一圈,居然没找到答案,于是打算写这篇博客.不知是否有更好的实践 ...
- Kuernetes-设计架构(二)
Kubernetes设计架构 Kubernetes集群包含有节点代理kubelet和Master组件(APIs,scheduler.etc),一切都基于分布式的存储系统.Kubernetes架构图: ...
- Ehcache缓存实例
一:目录 EhCache 简介 Hello World 示例 Spring 整合 Dummy CacheManager 的配置和作用 二: 简介 1. 基本介绍 EhCache 是一个纯Java的进程 ...
- CSS3实现3d菜单翻转
transform-style:flat | preserve-3d: 3d透视属性.针对子元素如何在3d空间相对其父元素渲染,这个属性声明在父元素上,并且他的子元素使用了transform才会有效. ...
- 雷哥带你走进Javascript
javascript复习笔记--------------------------------------------1.概念2.面向对象思想3.作用认识4.引入方式5.执行顺序 变量 1)声明方式 x ...
- 6.0 实现app登录
1.0.0:学习ui自动化准备工作 待测app,我这里有准备两个apk,这两个都是我曾经做过的项目,后续的文章都是基于这两个app! 链接:https://pan.baidu.com/s/1I0vR9 ...
- 01-Mysql数据库----前戏
MySql的前戏 在学习Mysql之前,我们先来想一下一开始做的登录注册案例,当时我们把用户的信息保存到一个文件中: #用户名 |密码root|123321 alex|123123 上面文件内容的规则 ...