【BZOJ2668】[cqoi2012]交换棋子

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

题解:容易想到费用流,从S向原图中所有1连边,新图中所有1向T连边,中间边的费用是1。但是中间的边我们既要限制入度又要限制出度,该怎么连呢?

我们仔细观察发现,如果相邻的两个都是1或都是0肯定不会交换,也就是说我们每次交换都会导致当前点的颜色改变。即如果当前点原图是0新图是0或原图是1新图是1,则该点的入度=出度;如果原图是1新图是0,则入度+1=出度;原图是0新图是1,则入度=出度+1。这样的话解个方程就知道具体的入度和出度限制了,所以我们只需要限制一下入度即可。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <queue>
  5. using namespace std;
  6. queue<int> q;
  7. int n,m,ta,tb,S,T,cnt,ans;
  8. char s1[30][30],s2[30][30],s3[30][30];
  9. inline int _(int a,int b) {return (a-1)*m+b;}
  10. inline int __(int a,int b) {return (a-1)*m+b+n*m;}
  11. int to[400010],next[400010],head[1010],cost[400010],flow[400010],dis[1010],pe[1010],pv[1010],inq[1010];
  12. inline void add(int a,int b,int c,int d)
  13. {
  14. to[cnt]=b,cost[cnt]=c,flow[cnt]=d,next[cnt]=head[a],head[a]=cnt++;
  15. to[cnt]=a,cost[cnt]=-c,flow[cnt]=0,next[cnt]=head[b],head[b]=cnt++;
  16. }
  17. inline int bfs()
  18. {
  19. memset(dis,0x3f,sizeof(dis));
  20. dis[S]=0,q.push(S);
  21. int i,u;
  22. while(!q.empty())
  23. {
  24. u=q.front(),q.pop(),inq[u]=0;
  25. for(i=head[u];i!=-1;i=next[i]) if(flow[i]&&dis[to[i]]>dis[u]+cost[i])
  26. {
  27. dis[to[i]]=dis[u]+cost[i],pe[to[i]]=i,pv[to[i]]=u;
  28. if(!inq[to[i]]) inq[to[i]]=1,q.push(to[i]);
  29. }
  30. }
  31. return dis[T]<0x3f3f3f3f;
  32. }
  33. int main()
  34. {
  35. memset(head,-1,sizeof(head));
  36. scanf("%d%d",&n,&m),S=0,T=2*n*m+1;
  37. int i,j,a,b;
  38. for(i=1;i<=n;i++)
  39. {
  40. scanf("%s",s1[i]+1);
  41. for(j=1;j<=m;j++) if(s1[i][j]=='1') ta++,add(S,_(i,j),0,1);
  42. }
  43. for(i=1;i<=n;i++)
  44. {
  45. scanf("%s",s2[i]+1);
  46. for(j=1;j<=m;j++) if(s2[i][j]=='1') tb++,add(_(i,j),T,0,1);
  47. }
  48. if(ta!=tb)
  49. {
  50. puts("-1");
  51. return 0;
  52. }
  53. for(i=1;i<=n;i++)
  54. {
  55. scanf("%s",s3[i]+1);
  56. for(j=1;j<=m;j++)
  57. {
  58. if(s3[i][j]-'0'-s1[i][j]+s2[i][j]<0)
  59. {
  60. puts("-1");
  61. return 0;
  62. }
  63. add(__(i,j),_(i,j),1,(s3[i][j]-'0'-s1[i][j]+s2[i][j])>>1);
  64. for(a=i-1;a<=i+1;a++) for(b=j-1;b<=j+1;b++) if((a!=i||b!=j)&&a&&b&&a<=n&&b<=m)
  65. add(_(i,j),__(a,b),0,1<<30);
  66. }
  67. }
  68. while(bfs())
  69. {
  70. ta--,ans+=dis[T];
  71. for(i=T;i!=S;i=pv[i]) flow[pe[i]]--,flow[pe[i]^1]++;
  72. }
  73. printf("%d",ta?-1:ans);
  74. return 0;
  75. }//1 3 100 001 121

【BZOJ2668】[cqoi2012]交换棋子 费用流的更多相关文章

  1. BZOJ2668: [cqoi2012]交换棋子(费用流)

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

  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. spring boot 拦截器之WebMvcConfigurerAdapter

    版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   上一篇我们讲到了拦截器,我们也简单的讲解到了WebMvcConfigurerAdapter这个拦截器.本篇我们来对Web ...

  2. 你可能并不需要一个 CTO

    转自:http://dbanotes.net/CTO 有朋友在微信里让我给推荐一个 CTO.说是一家公司在找人,据说「项目不错」,因为之前的业务不是很互联网,现在有一个新的项目要做,要做一个社会化电商 ...

  3. selenium测试(Java)--告警框处理(十四)

    下面代码中介绍了告警框的处理方法 package com.test.alerthandle; import org.openqa.selenium.By; import org.openqa.sele ...

  4. 【F12】网络面板

    使用网络面板了解请求和下载的资源文件并优化网页加载性能 (1)网络面板基础 测量资源加载时间 使用 Network 面板测量您的网站网络性能. Network 面板记录页面上每个网络操作的相关信息,包 ...

  5. netsnmp编译动态库

    .编译动态库 将写完的snmp代理程序编译生成动态库 gcc -c -fpic telnetConfig.c -o telnetConfig.o -I/usr/local/net-snmp/inclu ...

  6. linux -- Apache执行权限

    最近在用php调用exec方法去执行一个linux终端下的命令,结果每次都不能执行成功,网上多番搜寻,最终找到一篇有用的文章,主要原因是因为Apache的执行权限的问题.以下是原文(稍加修改): 利用 ...

  7. MySQL无法远程连接解决方案

    1.查看/etc/mysql/my.cnf配置文件是否只允许本地连接 注释配置:#bind-address = 127.0.0.1,重启MySQL Server 2.防火墙(我用的是iptables) ...

  8. par函数bty参数-控制绘图边框

    bty 可以看作box type 的缩写,控制绘图边框的显示,取值范围为o, l, u, c, ], n 默认值为"o", 代码示例: par(bty = "o" ...

  9. opengl 模板测试 glStencilOp glStencilFunc

    下面来设置蒙板缓存和蒙板测试. 首先我们启用蒙板测试,这样就可以修改蒙板缓存中的值. 下面我们来解释蒙板测试函数的含义: 当你使用glEnable(GL_STENCIL_TEST)启用蒙板测试之后,蒙 ...

  10. Hbase学习之javaApI封装

    http://qindongliang.iteye.com/blog/2096140