【题解】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]$ ,以下为建图方式: ...
随机推荐
- jQuery-qrcode.js 生成带Logo 的二维码
引入文件 jQuery-qrcode.js 地址:https://blog-static.cnblogs.com/files/kitty-blog/jquery-qrcode.js https:// ...
- js根据年份获取某月份有几天
function getNum(year, month) { var temp; month = parseInt(month, 10); temp = new Date(year, month, 0 ...
- cnpm 下载
1, 如果电脑已经有node的话,可以先卸载,然后再去node官网下载最新node, 2,先全局安装cnpm, npm install -g cnpm --registry=https://regis ...
- React学习(3)——Router路由的使用和页面跳转
React-Router的中文文档可以参照如下链接: http://react-guide.github.io/react-router-cn/docs/Introduction.html 文档中介绍 ...
- Hadoop(11)-MapReduce概述和简单实操
1.MapReduce的定义 2.MapReduce的优缺点 优点 缺点 3.MapReduce的核心思想 4.MapReduce进程 5.常用数据序列化类型 6.MapReduce的编程规范 用户编 ...
- CPS---(Cyber-Physical Sytem,信息物理融合系统)
1.CPS定义 CPS是连接计算机虚拟世界与物理现实世界的系统.---We refer to systems that bridge the cyber-world of computing and ...
- Scrapy之Cookie和代理
cookie cookie: 获取百度翻译某个词条的结果 一定要对start_requests方法进行重写. 两种解决方案: 1. Request()方法中给method属性赋值成post2. For ...
- CMDB介绍
CMDB https://lupython.gitee.io/2018/05/05/CMDB%E4%BB%8B%E7%BB%8D/ 尚泽凯博客地址 传统运维与自动化运维的区别 传统运维: 1.项目 ...
- Java学习笔记十三:Java中的类和对象
Java中的类和对象 一:什么是对象: 总的来说就是"万物皆对象",客观存在的事物皆为对象.是计算机所关注的具体信息. 对象(object)是一件事.一个物体.一个名词,或可以获得 ...
- 【Java】关于Spring框架的总结 (三)
前文对 Spring IoC 和 Spring AOP 的实现方法进行了整合.如果有不明白的或有质疑的地方可以评论出来,一起探讨问题,帮助别人也是帮助自己!本文探讨的中心主要放在 Spring 的注解 ...