Description

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

Input

第一行包含两个整数nm(1<=nm<=20)。以下n行为初始状态,每行为一个包含m个字符的01串,其中0表示黑色棋子,1表示白色棋子。以下n行为目标状态,格式同初始状态。以下n行每行为一个包含m个0~9数字的字符串,表示每个格子参与交换的次数上限。
 

Output

输出仅一行,为最小交换总次数。如果无解,输出-1。

Sample Input

3 3
110
000
001
000
110
100
222
222
222

Sample Output

4

解题思路:

这道题可以发现费用流肯定是可以解决的。
问题是怎么建图。
易知每步交换一定是一黑一白。
所以就可以考虑每个点前后的变化来得到白变黑次数的上限。
这个只与前后黑白状态有关。
若状态相同,则白变黑次数=黑变白次数。
不同则讨论即可。
一定是一个比另外一个大一。
这样就可以确定流入和流出上限。
现在考虑流量守恒,发现白黑相同时无流量变化,黑白不同时边权也守恒。
发现这样只需要新建两个新节点来达到建图的目的。
代码:
 #include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long lnt;
const int oo=0x3f3f3f3f;
const int di[]={,,-,,,,-,-};
const int dj[]={-,,,,-,,,-};
struct pnt{
int hd;
int dis;
int val;
int pre;
int lst;
bool vis;
}p[];
struct ent{
int twd;
int lst;
int vls;
int dis;
}e[];
int cnt;
int n,m;
int s,t;
int maxflow;
int no[][];
int st[][];
int ed[][];
int vl[][];
std::queue<int>Q;
void ade_(int f,int t,int v,int d)
{
cnt++;
e[cnt].twd=t;
e[cnt].vls=v;
e[cnt].dis=d;
e[cnt].lst=p[f].hd;
p[f].hd=cnt;
return ;
}
void adde(int f,int t,int v,int d)
{
ade_(f,t,v,d);
ade_(t,f,,-d);
return ;
}
bool Spfa(void)
{
while(!Q.empty())Q.pop();
for(int i=;i<=t;i++)
{
p[i].dis=p[i].val=oo;
p[i].pre=-;
p[i].vis=false;
}
Q.push(s);
p[s].vis=true;
p[s].dis=;
while(!Q.empty())
{
int x=Q.front();
Q.pop();
p[x].vis=false;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].dis>p[x].dis+e[i].dis&&e[i].vls)
{
p[to].dis=p[x].dis+e[i].dis;
p[to].pre=x;
p[to].lst=i;
p[to].val=std::min(p[x].val,e[i].vls);
if(p[to].vis)continue;
p[to].vis=true;
Q.push(to);
}
}
}
return p[t].pre!=-;
}
int Ek(void)
{
int ans=;
while(Spfa())
{
maxflow+=p[t].val;
ans+=p[t].dis*p[t].val;
for(int i=t;i!=s;i=p[i].pre)
{
e[p[i].lst].vls-=p[t].val;
e[((p[i].lst-)^)+].vls+=p[t].val;
}
}
return ans;
}
int main()
{
int a1(),a2();
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)for(int j=;j<=m;j++)no[i][j]=++cnt;
s=cnt*+,t=s+;
cnt=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%1d",&st[i][j]),a1+=st[i][j];
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%1d",&ed[i][j]),a2+=ed[i][j];
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%1d",&vl[i][j]);
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
if(!st[i][j])adde(s,no[i][j],,);
if(!ed[i][j])adde(no[i][j],t,,);
int frm,twd;
if(st[i][j]==ed[i][j])frm=twd=vl[i][j]/;
if(st[i][j]>ed[i][j])frm=(vl[i][j]+)/,twd=vl[i][j]/;
if(st[i][j]<ed[i][j])twd=(vl[i][j]+)/,frm=vl[i][j]/;
adde(no[i][j]+n*m,no[i][j],frm,);
adde(no[i][j],no[i][j]+*n*m,twd,);
for(int d=;d<;d++)
{
int ii=di[d]+i;
int jj=dj[d]+j;
if(!no[ii][jj])continue;
adde(no[i][j]+*n*m,no[ii][jj]+m*n,oo,); }
}
}
int ans=Ek();
if(m*n-maxflow!=a1||a1!=a2)ans=-;
printf("%d\n",ans);
return ;
}

BZOJ2668: [cqoi2012]交换棋子(费用流)的更多相关文章

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

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

  2. [CQOI2012] 交换棋子 - 费用流

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

  3. BZOJ.2668.[CQOI2012]交换棋子(费用流zkw)

    题目链接 首先黑白棋子的交换等价于黑棋子在白格子图上移动,都到达指定位置. 在这假设我们知道这题用网络流做. 那么黑棋到指定位置就是一条路径,考虑怎么用流模拟出这条路径. 我们发现除了路径的起点和终点 ...

  4. BZOJ2668: [cqoi2012]交换棋子

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

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

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

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

    题目链接 BZOJ2668 题解 容易想到由\(S\)向初始的黑点连边,由终态的黑点向\(T\)连边,然后相邻的点间连边 但是这样满足不了交换次数的限制,也无法计算答案 考虑如何满足一个点的交换次数限 ...

  7. [CQOI2012][bzoj2668] 交换棋子 [费用流]

    题面 传送门 思路 抖机灵 一开始看到这题我以为是棋盘模型-_-|| 然而现实是骨感的 后来我尝试使用插头dp来交换,然后又惨死 最后我不得不把目光转向那个总能化腐朽为神奇的算法:网络流 思维 我们要 ...

  8. 【BZOJ-2668】交换棋子 最小费用最大流

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

  9. [cqoi2012]交换棋子

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

随机推荐

  1. Qt5的插件机制(1)--Qt 框架中的插件载入机制概述

    概述 Qt的源代码中通过 Q<pluginType>Factory.Q<pluginType>Plugin 和 Q<pluginType> 这三个类实现了Qt的插件 ...

  2. Android Studio生成apk

    1.菜单Build->Generate Signed APK 2.生成android.keystore,能够依据弹框去Create new一个,也可使用命令来生成android.keystore ...

  3. zookeeper应用场景练习(分布式锁)

    在寻常的高并发的程序中.为了保证数据的一致性.因此都会用到锁.来对当前的线程进行锁定.在单机操作中.非常好做到,比方能够採用Synchronized.Lock或者其它的读写多来锁定当前的线程.可是在分 ...

  4. 在jqueryEasyUI界面将时间以日期加时分秒的格式显示

    问题描写叙述: oracle 10G中用户表有一个字段是日期型.数据格式为yyyy-MM-dd HH:mm:ss,前端显示时仅仅能显示成yyyy-MM-dd 后面的 HH:mm:ss不显示. 经过一番 ...

  5. pre自动换行

    从word复制到html中的文本,用pre能够原汁原味的展示出来,但是会出现超过屏蔽界限的情况. 需要进行换行处理. 加上一句css pre { white-space: pre-wrap; word ...

  6. PermissionError: [Errno 13] in python

    出现该错误,首先尝试以管理员身份运行 cmd.exe 程序,然后关闭所有的与 python 相关的进程. 1. open 打开一个文件夹(目录),而不是文件 这一错误一般发生在使用 open函数对文件 ...

  7. BZOJ 3931 Dijkstra+网络流

    思路: (我能说按照题意模拟么) 用long long inf 要开大--. //By SiriusRen #include <queue> #include <cstdio> ...

  8. 我照着NancyFx官网的demo来做为什么会有错误呢????

    我照着NancyFx官网的demo来做为什么会有错误呢???? >> csharp这个答案描述的挺清楚的:http://www.goodpm.net/postreply/csharp/10 ...

  9. JavaScript总结(3)

    第3章 获取用户的输入 <script>10 intA=prompt("请输入第一个数字","");11 intB=prompt("请输入 ...

  10. Bayes++ Library入门学习之熟悉class-Bayesian_filter_base(1)

    在对Bayes++库的名称空间有了一个大概的了解之后,我们开始学习该名称空间下的第一个子类Bayesian_filter::Bayes_filter_base. 该类与其子类的继承关系图如下图所示. ...