巧妙的拆点方式,首先把1看成黑点,0看成空的,几次交换就可以看成一条路径

1)从容量上看,这条路径为1-2-2-2-2-2-……-2-1

2)从费用上看,这条路径每条边费用都是1

于是用一种巧妙的拆点方式,把一个点拆成三个,连两条边,成为一条链,

然后如果是黑点的话就由s向中间那个点连边,如果是路过的话就由一条链的尾部向另一条链的首部连边

这样就满足了上面的条件1)2)

容量的话如果是黑点出来就是(c+1)/2,进来是c/2,其他的以此类推

 #include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#define rint register int
#define ll long long
#define MAXN 2000+10
#define pb push_back
#define INF 0x7f7f7f7f
#define oo 0x7f7f7f7f7f7f7f7f
#define pil pair<int,ll>
#define mp make_pair
using namespace std;
int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if('-'==ch)f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
struct E{
int from,to,cap,flow;
ll cost;
E(int x=,int y=,int c=,int f=,ll w=0LL){
from=x,to=y,cap=c,flow=f,cost=w;
}
};
struct Dinic{
int n,m,s,t;
vector<E> es;
vector<int> G[MAXN];
void init(int n,int s,int t){
this->n=n;
this->s=s,this->t=t;
es.clear();
for(int i=;i<=n;i++)G[i].clear();
}
void add(int x,int y,int cap,ll cost){
es.pb(E(x,y,cap,,cost));
es.pb(E(y,x,,,-cost));
m=es.size();
G[x].pb(m-),G[y].pb(m-);
}
int p[MAXN],a[MAXN];
ll d[MAXN];
int b[MAXN];
bool SPFA(int &flow,ll &cost){
p[s]=,a[s]=INF;
memset(d,0x7f,sizeof(d));
d[s]=;
memset(b,,sizeof(b));
b[s]=;
queue<int> q;
q.push(s);
while(!q.empty()){
int x=q.front();q.pop();b[x]=;
for(rint i=;i<G[x].size();i++){
E &e=es[G[x][i]];
if(e.cap>e.flow&&d[e.to]>d[x]+e.cost){
p[e.to]=G[x][i];
a[e.to]=min(a[x],e.cap-e.flow);
d[e.to]=d[x]+e.cost;
if(!b[e.to]){
b[e.to]=;
q.push(e.to);
}
}
}
}
if(oo==d[t]){
return ;
}
flow+=a[t];
cost+=a[t]*d[t];
for(rint i=t;i!=s;i=es[p[i]].from){
es[p[i]].flow+=a[t];
es[p[i]^].flow-=a[t];
}
return ;
}
pil MaxfMinc(){
int flow=;
ll cost=0LL;
while(SPFA(flow,cost));
return mp(flow,cost);
}
}D;
int n,m,s=,t=MAXN-;
int id[][][];
int a[][],b[][],p[][];
int cnt1=,cnt2=;
void init(){
n=read();m=read();
D.init(t,s,t);
char c[];
for(rint i=;i<=n;i++){
for(rint j=;j<=m;j++){
id[][i][j]=(i-)*m+j;
}
}
for(rint k=;k<=;k++){
for(rint i=;i<=n;i++){
for(rint j=;j<=m;j++){
id[k][i][j]=id[k-][i][j]+n*m;
}
}
}
for(rint i=;i<=n;i++){
scanf("%s",c+);
for(rint j=;j<=m;j++){
a[i][j]=c[j]-'';
}
}
for(rint i=;i<=n;i++){
scanf("%s",c+);
for(rint j=;j<=m;j++){
b[i][j]=c[j]-'';
}
}
for(rint i=;i<=n;i++){
for(rint j=;j<=m;j++){
if(a[i][j]&&b[i][j]){
a[i][j]=b[i][j]=;
}
else if(a[i][j]){
cnt1++;
}
else if(b[i][j]){
cnt2++;
}
}
}
for(rint i=;i<=n;i++){
scanf("%s",c+);
for(rint j=;j<=m;j++){
p[i][j]=c[j]-'';
}
}
}
void add(int x,int y,int c1,int c2){
D.add(id[][x][y],id[][x][y],c1,);
D.add(id[][x][y],id[][x][y],c2,);
}
void solve(){
int dx[]={,,-,,-,-,,};
int dy[]={,-,,,-,,-,};
for(rint i=;i<=n;i++){
for(rint j=;j<=m;j++){
if(a[i][j]){
add(i,j,p[i][j]>>,(p[i][j]+)>>);
D.add(s,id[][i][j],,);
}
else if(b[i][j]){
add(i,j,(p[i][j]+)>>,p[i][j]>>);
D.add(id[][i][j],t,,);
}
else{
add(i,j,(p[i][j]+)>>,p[i][j]>>);
}
for(rint k=;k<;k++){
int x=i+dx[k],y=j+dy[k];
if(<=x&&x<=n&&<=y&&y<=m){
D.add(id[][i][j],id[][x][y],INF,);
}
}
}
}
pil ans=D.MaxfMinc();
if(ans.first!=cnt1||cnt1!=cnt2){
printf("-1\n");
}
else{
printf("%d\n",ans.second);
}
}
int main()
{
init();
solve();
return ;
}

洛谷P3159 [CQOI2012]交换棋子的更多相关文章

  1. [bzoj2668] [洛谷P3159] [cqoi2012] 交换棋子

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

  2. P3159 [CQOI2012]交换棋子

    思路 相当神奇的费用流拆点模型 最开始我想到把交换黑色棋子看成一个流流动的过程,流从一个节点流向另一个节点就是交换两个节点,然后把一个位置拆成两个点限制流量,然后就有了这样的建图方法 S向所有初始是黑 ...

  3. BZOJ2668: [cqoi2012]交换棋子

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

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

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

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

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

  6. [cqoi2012]交换棋子

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

  7. [洛谷P3158] [CQOI2011]放棋子

    洛谷题目链接:[CQOI2011]放棋子 题目描述 在一个m行n列的棋盘里放一些彩色的棋子,使得每个格子最多放一个棋子,且不同 颜色的棋子不能在同一行或者同一列.有多少祌方法?例如,n=m=3,有两个 ...

  8. 洛谷 P3182 [HAOI2016]放棋子(高精度,错排问题)

    传送门 解题思路 不会错排问题的请移步——错排问题 && 洛谷 P1595 信封问题 这一道题其实就是求对于每一行的每一个棋子都放在没有障碍的地方的方案数. 因为障碍是每行.每列只有一 ...

  9. 洛谷P3158 [CQOI2011]放棋子 组合数学+DP

    题意:在一个m行n列的棋盘里放一些彩色的棋子,使得每个格子最多放一个棋子,且不同颜色的棋子不能在同一行或者同一列.有多少祌方法? 解法:这道题不会做,太菜了qwq.题解是看洛谷大佬的. 设C是组合数, ...

随机推荐

  1. Alpha冲刺集合

    Alpha冲刺集合 Day1 http://www.cnblogs.com/bugLoser/p/7901016.html Day2 http://www.cnblogs.com/bugLoser/p ...

  2. 冲刺NO.5

    Alpha冲刺第五天 站立式会议 项目进展 今日项目完成内容主要包括了JS的学习,事务管理员模块与学生模块的完善与补充,并且开始编写信用信息管理模块和奖惩事务管理模块. 问题困难 前端部分的技术掌握的 ...

  3. MariaDB/MySQL存储过程和函数

    本文目录:1.创建存储过程.函数 1.1 存储过程的IN.OUT和INOUT2.修改和删除存储过程.函数3.查看存储过程.函数信息 在MySQL/MariaDB中,存储过程(stored proced ...

  4. New UWP Community Toolkit - AdaptiveGridView

    概述 UWP Community Toolkit  中有一个自适应的 GridView 控件 - AdaptiveGridView,本篇我们结合代码详细讲解  AdaptiveGridView 的实现 ...

  5. intellij idea 找不到或无法加载主类

    解决intellij idea 找不到或无法加载主类,请看以下图文介绍 然后idea会重启,等idea启动后 右侧的maven clean 一下,然后再compile就解决了

  6. MSIL实用指南-一维数组的操作

    本篇讲解怎么生成和操作一维数组.各种数组类型创建的步骤是一样的,但是加载和保存步骤有所不同. 一.创建数组所有类型的一维数组创建都是一样的,分三步.1.加载数组长度2.生成指令 Newarr < ...

  7. Python 简单聊天室

    #coding=utf-8 from socket import * from threading import Thread import time udpSocket = socket(AF_IN ...

  8. 自动化服务部署(一):Linux下安装JDK

    自动化测试的主要目的是为了执行回归测试.当然,为了模拟真实的用户操作,一般都是在UAT或者生产环境进行回归测试. 为了尽量避免内网和外网解析对测试结果的影响,将自动化测试服务部署在外网的服务器是比较好 ...

  9. Python内置函数(53)——setattr

    英文文档: setattr(object, name, value) This is the counterpart of getattr(). The arguments are an object ...

  10. CURL学习总结(1)

    1.curl是什么?         百度百科定义:     curl是利用URL语法在命令行方式下工作的开源文件传输工具.它被广泛应用在Unix.多种Linux发行版中,并且有DOS和Win32.W ...