传送门

好难的网络流啊,建图真的超难。

如果不告诉我是网络流的话,我估计就会写dfs了。

使用费用流解决本题,设点 $p[i][j]$ 的参与交换的次数上限为 $v[i][j]$ ,以下为建图方式:

  1. 将一个点分成三个点,分别为入点,原点和出点。

  2. 如果开始的图上该位置有棋子,那么从S到该点的原点连一条边权1,费用0的边

  3. 如果结束的图上该位置有棋子,那么从该点的原点到T连一条边权1,费用0的边

  4. 如果该点只在开始的图上出现,那么从该点的入点向原点连一条边权为 $v[i][j]/2$ ,费用为1的边,从该点的原点向出点连一条边权为 $(v[i][j]+1)/2$ ,费用为0的边

  5. 如果该点只在结束的图上出现,那么从该点的入点向原点连一条边权为 $(v[i][j]+1)/2$ ,费用为1的边,从该点的原点向出点连一条边权为 $v[i][j]/2$ ,费用为0的边

  6. 如果以上两点都不符合,那么从该点的入点向原点连一条边权为 $v[i][j]/2$ ,费用为1的边,从该点的原点向出点连一条边权为 $v[i][j]/2$ ,费用为0的边

——by zhouyonglong

我只是题解的搬运工。

最后把每个点的原点和它相邻的点的原点连一条容量为INF,费用为0的边

  1. #include <queue>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <iostream>
  5. #include <algorithm>
  6. #define N 1000001
  7. #define id(i, j, k) ((i - 1) * m + j + (k - 1) * n * m)
  8.  
  9. using namespace std;
  10.  
  11. int n, m, cnt, s, t, ans, sum1, sum2, sum;
  12. int head[N], to[N], nex[N], val[N], cost[N], dis[N], pre[N], path[N];
  13. char s1[21][21], s2[21][21], c[21][21];
  14. const int dx[8] = {1, 1, 0, -1, -1, -1, 0, 1}, dy[8] = {0, 1, 1, 1, 0, -1, -1, -1};
  15. bool vis[N];
  16.  
  17. inline int read()
  18. {
  19. int x = 0, f = 1;
  20. char ch = getchar();
  21. for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
  22. for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
  23. return x * f;
  24. }
  25.  
  26. inline void add(int x, int y, int z, int v)
  27. {
  28. to[cnt] = y;
  29. val[cnt] = z;
  30. cost[cnt] = v;
  31. nex[cnt] = head[x];
  32. head[x] = cnt++;
  33. }
  34.  
  35. inline bool spfa()
  36. {
  37. int i, u, v;
  38. queue <int> q;
  39. memset(vis, 0, sizeof(vis));
  40. memset(pre, -1, sizeof(pre));
  41. memset(dis, 127, sizeof(dis));
  42. q.push(s);
  43. dis[s] = 0;
  44. while(!q.empty())
  45. {
  46. u = q.front();
  47. vis[u] = 0;
  48. q.pop();
  49. for(i = head[u]; ~i; i = nex[i])
  50. {
  51. v = to[i];
  52. if(val[i] && dis[v] > dis[u] + cost[i])
  53. {
  54. dis[v] = dis[u] + cost[i];
  55. pre[v] = u;
  56. path[v] = i;
  57. if(!vis[v])
  58. {
  59. q.push(v);
  60. vis[v] = 1;
  61. }
  62. }
  63. }
  64. }
  65. return pre[t] != -1;
  66. }
  67.  
  68. inline void E()
  69. {
  70. puts("-1"), exit(0);
  71. }
  72.  
  73. int main()
  74. {
  75. int i, j, k, x, y, f;
  76. n = read();
  77. m = read();
  78. s = 0, t = 3 * n * m + 1;
  79. memset(head, -1, sizeof(head));
  80. for(i = 1; i <= n; i++) scanf("%s", s1[i] + 1);
  81. for(i = 1; i <= n; i++) scanf("%s", s2[i] + 1);
  82. for(i = 1; i <= n; i++) scanf("%s", c[i] + 1);
  83. for(i = 1; i <= n; i++)
  84. for(j = 1; j <= m; j++)
  85. {
  86. c[i][j] -= '0';
  87. if(s1[i][j] == '1')
  88. {
  89. sum1++;
  90. add(s, id(i, j, 2), 1, 0);
  91. add(id(i, j, 2), s, 0, 0);
  92. }
  93. if(s2[i][j] == '1')
  94. {
  95. sum2++;
  96. add(id(i, j, 2), t, 1, 0);
  97. add(t, id(i, j, 2), 0, 0);
  98. }
  99. if(s1[i][j] == '1' && s2[i][j] == '0')
  100. {
  101. add(id(i, j, 1), id(i, j, 2), c[i][j] / 2, 1);
  102. add(id(i, j, 2), id(i, j, 1), 0, -1);
  103. add(id(i, j, 2), id(i, j, 3), (c[i][j] + 1) / 2, 0);
  104. add(id(i, j, 3), id(i, j, 2), 0, 0);
  105. }
  106. if(s1[i][j] == '0' && s2[i][j] == '1')
  107. {
  108. add(id(i, j, 1), id(i, j, 2), (c[i][j] + 1) / 2, 1);
  109. add(id(i, j, 2), id(i, j, 1), 0, -1);
  110. add(id(i, j, 2), id(i, j, 3), c[i][j] / 2, 0);
  111. add(id(i, j, 3), id(i, j, 2), 0, 0);
  112. }
  113. if(s1[i][j] == s2[i][j])
  114. {
  115. add(id(i, j, 1), id(i, j, 2), c[i][j] / 2, 1);
  116. add(id(i, j, 2), id(i, j, 1), 0, -1);
  117. add(id(i, j, 2), id(i, j, 3), c[i][j] / 2, 0);
  118. add(id(i, j, 3), id(i, j, 2), 0, 0);
  119. }
  120. for(k = 0; k < 8; k++)
  121. {
  122. x = i + dx[k];
  123. y = j + dy[k];
  124. if(1 <= x && x <= n && 1 <= y && y <= m)
  125. {
  126. add(id(i, j, 3), id(x, y, 1), 1e9, 0);
  127. add(id(x, y, 1), id(i, j, 3), 0, 0);
  128. }
  129. }
  130. }
  131. if(sum1 != sum2) E();
  132. while(spfa())
  133. {
  134. f = 1e9;
  135. for(i = t; i != s; i = pre[i]) f = min(f, val[path[i]]);
  136. sum += f;
  137. ans += dis[t];
  138. for(i = t; i != s; i = pre[i])
  139. {
  140. val[path[i]] -= f;
  141. val[path[i] ^ 1] += f;
  142. }
  143. }
  144. if(sum != sum1) E();
  145. printf("%d\n", ans);
  146. return 0;
  147. }

  

[luoguP3159] [CQOI2012]交换棋子(最小费用最大流)的更多相关文章

  1. BZOJ 2668 [cqoi2012]交换棋子 | 最小费用最大流

    传送门 BZOJ 2668 题解 同时分别限制流入和流出次数,所以把一个点拆成三个:入点in(x).中间点mi(x).出点ou(x). 如果一个格子x在初始状态是黑点,则连(S, mi(x), 1, ...

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

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

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

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

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

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

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

    $pdf\space solution$    link #include<iostream> #include<cstring> #include<cstdio> ...

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

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

  7. [cqoi2012]交换棋子

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

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

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

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

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

随机推荐

  1. JS判断两个对象相同属性的属性值是否相等

    function isObjectValueEqual(a, b) { var aProps = Object.getOwnPropertyNames(a); var bProps = Object. ...

  2. siege4安装和使用介绍

    使用文档参考地址:https://www.joedog.org/siege-manual/ siege4地址:http://download.joedog.org/siege/ cd /usr/loc ...

  3. React学习实例总结,包含yeoman安装、webpack构建

    1.安装yeoman 在安装nodeJs的基础上,输入命令:npm install -g yo grunt-cli bower,安装yeoman,grunt,bowerify 安装完成后,输入命令:y ...

  4. python_113_socket编程

    Socket语法及相关 socket概念 socket本质上就是在2台网络互通的电脑之间,架设一个通道,两台电脑通过这个通道来实现数据的互相传递. 我们知道网络 通信 都 是基于 ip+port 方能 ...

  5. 一张图看懂苹果MacBook所有屏幕分辨率

    苹果全新12寸超薄MacBook比曾经最薄的MacBook Air更薄,不过却配备了Retina视网膜显示屏.12英寸RetinaMacBook上的显示屏分辨率为2304*1440,虽然不如15寸和1 ...

  6. BOM函数之history对象

    前面的话 history对象保存着用户上网的历史记录,从窗口被打开的那一刻算起.由于安全方面的考虑,开发人员无法得到用户浏览器的URL,但借由用户访问过的页面列表,可以在不知道实际URL的情况下实现后 ...

  7. Ibatis入门基本语法

    1.       Ibatis是开源软件组织Apache推出的一种轻量级的对象关系映射(ORM)框架,和Hibernate.Toplink等在java编程的对象持久化方面深受开发人员欢迎. 对象关系映 ...

  8. Luogu P2397 yyy loves Maths VI (mode)

    题目传送门 虽然只是一道黄题,但还是学到了一点新知识-- 摩尔投票法 用\(O(1)\)的内存,\(O(n)\)的时间来找出一串长度为n的数中的众数,前提是众数出现的次数要大于\(n/2\) 方法很简 ...

  9. shell脚本,锁机制

    [root@localhost wyb]# cat suijizhi.sh #!/bin/bash a=`|grep -v grep |wc -l` echo "$a" [ $a ...

  10. easyUI 之datagrid 在前端自定义排序

    首先先来看一下,直接从后台读取数据并展示到前端的列表,后端传回的数据是“按商品ID倒序排列” 前端源代码 $('#good_tables').datagrid({ nowrap: true, auto ...