巧妙的拆点方式,首先把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. BEM 中文翻译

    BEM 原文请看 getBEM Introduction(介绍) Block 独立实体,独立的意义 Examples:header, container, menu, checkbox, input ...

  2. nyoj 聪明的kk

    聪明的kk 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 聪明的"KK"非洲某国展馆的设计灵感源于富有传奇色彩的沙漠中陡然起伏的沙丘,体现出本国 ...

  3. JAVA_SE基础——40.super关键字

    只要this关键字掌握了,super关键字不在话下,因为他们原理都差不多的.. this&super 什么是this,this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针 ...

  4. Java面试题(二)

    系统整理了一下有关Java的面试题,包括基础篇,javaweb篇,框架篇,数据库篇,多线程篇,并发篇,算法篇等等,陆续更新中.其他方面如前端后端等等的面试题也在整理中,都会有的. 注:文末有福利! 1 ...

  5. 详解k8s一个完整的监控方案(Heapster+Grafana+InfluxDB) - kubernetes

    1.浅析整个监控流程 heapster以k8s内置的cAdvisor作为数据源收集集群信息,并汇总出有价值的性能数据(Metrics):cpu.内存.网络流量等,然后将这些数据输出到外部存储,如Inf ...

  6. 使用 BenchmarkDotnet 测试代码性能

    先来点题外话,清明节前把工作辞了(去 tm 的垃圾团队,各种拉帮结派.勾心斗角).这次找工作就得慢慢找了,不能急了,希望能找到个好团队,好岗位吧.顺便这段时间也算是比较闲,也能学习一下和填掉手上的坑. ...

  7. kafka---broker 保存消息

    1 .存储方式 物理上把 topic 分成一个或多个 patition(对应 server.properties 中的 num.partitions=3 配置),每个 patition 物理上对应一个 ...

  8. netty学习--handler传递

    在netty中的处理链pipeline中,事件是按顺序传递的,把自己拟人为netty程序,针对进来(inbound)的请求,会从head开始,依次往tail传递. pipeline采用了链表结构,he ...

  9. python基础——特性(property)、静态方法(staticmethod)和类方法(classmethod)

    python基础--特性(property) 1 什么是特性property property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值 import math class Circl ...

  10. hdu-2639 Bone Collector II---第k大背包

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2639 题目大意: 求第k大背包. 思路: 由01背包递推式dp[i][j] = max(dp[i][ ...