感受到网络流的强大了……这道题目的关键在于:

  前后颜色不变的,流入流出的次数相等;原本是黑色的最后变成了白色,流出比流入次数多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交换棋子的更多相关文章

  1. BZOJ2668: [cqoi2012]交换棋子

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

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

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

  3. BZOJ 2668: [cqoi2012]交换棋子

    2668: [cqoi2012]交换棋子 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1112  Solved: 409[Submit][Status ...

  4. [cqoi2012]交换棋子

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

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

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

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

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

  7. [CQOI2012]交换棋子 网络流

    ---题面--- 题解: 一开始很快想出了一个接近正解的建图方法,但其实是错误的,不过还是骗了70分_(:зゝ∠)_ 首先我们可以观察到棋子有限,但费用多种,其实也就相当于限制了流量,找最小费用 对于 ...

  8. BZOJ2668:[CQOI2012]交换棋子(费用流)

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

  9. [luoguP3159] [CQOI2012]交换棋子(最小费用最大流)

    传送门 好难的网络流啊,建图真的超难. 如果不告诉我是网络流的话,我估计就会写dfs了. 使用费用流解决本题,设点 $p[i][j]$ 的参与交换的次数上限为 $v[i][j]$ ,以下为建图方式: ...

随机推荐

  1. 配置Struts2及Struts2访问servlet api的方式

    Struts2的起源与背景 在很长的一段时间内,在所有的MVC框架中,Struts1处于绝对的统治地位,无论是从市场的普及范围,还是具体的使用者数量. 其他MVC框架都无 法与其相比,作为一一款优秀的 ...

  2. 为何要搭建ES6开发环境,如何搭建ES6开发环境?

    1.ES6需要搭建开发环境,原因是现在的Chrome浏览器已经支持ES6了,但是有些低版本的浏览器还是不支持ES6语法的,这就需要我们把ES6的语法自动转变成ES5的语法.   2.开始搭建环境   ...

  3. Object.keys方法

    我们有时需要知道对象的所有属性,原生js给我们提供了一个很好的方法:Object.keys(),该方法返回一个数组 传入对象,返回属性名 var obj = {'a':'123','b':'345'} ...

  4. 【PHP项目】产品新增的多图上传

    产品新增:多图上传 1:html的更改 在 type=file的input框中添加multiple="multiple" name属性中必须添加[] ,否则$_FILES只能接收最 ...

  5. 日志管理——rsyslog

    官方文档(必看) http://www.rsyslog.com/doc/v8-stable/ 简介 rsyslog是linux自带日志管理工具,分为客户端\服务端,包含日志收集\过滤\分析\转储. 数 ...

  6. ruby编码说明

    程序编码一般分几种情况: 1.源码文件编码 2.接收外部内容的编码 3.运行环境编码 4.操作系统编码 首先源码文件的编码,可以通过在ruby文件的头部添加一行申明即可,这样所有在源码里面出现的字符都 ...

  7. 基于vue来开发一个仿饿了么的外卖商城(二)

    一.抽出头部作为一个组件,在底部导航的时候可以相应的显示不同的标题 技术点:使用slot进行组件间的通信:父组件给子组件传值(子组件里面通过props接收父组件传过来的数据) 查看链接:https:/ ...

  8. Win10正式版激活

    参考:https://jingyan.baidu.com/article/47a29f2457af76c015239942.html https://jingyan.baidu.com/article ...

  9. hoj第三场G-manhattanp ositioning system

    ---恢复内容开始--- 一.题意 在二维坐标系内,给定若干个点和目标点距离该点的曼哈顿距离,求是否存在唯一解使得目标点坐标为整数. 二.题解 重新思考题目模型,考虑曼哈顿距离一定时,几何含义为,以给 ...

  10. IDEA常用操作(一)

    1.视图的调整 左下右的侧边栏如何关闭?——右击选择remove from sidebar 面板上(左下右)的导航栏视图如何隐藏——可以在左下角悬停显示,单击隐藏/开启侧边栏 想打开其它视图怎么办?— ...