[关闭]
@ZCDHJ 2018-09-26T16:45:22.000000Z 字数 1727 阅读 605

BJOI2006 狼抓兔子

网络流


BZOJ

题目很显然是要求最小割

根据最大流最小割定理,直接上 Dinic 就行了。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <queue>
  5. const int INF = 0x3f3f3f3f;
  6. const int MAXN = 1e3;
  7. int n, m, edge = -1;
  8. int firstEdge[MAXN * MAXN + 5], depth[MAXN * MAXN + 5], curE[MAXN * MAXN + 5], id[MAXN + 5][MAXN + 5];
  9. struct Edge {
  10. int to, w, nxt;
  11. Edge(){}
  12. Edge(int x, int y, int z) {
  13. to = y;
  14. w = z;
  15. nxt = firstEdge[x];
  16. }
  17. } e[(2 * MAXN * MAXN + 4 * MAXN) * 3 + 5];
  18. inline int read() {
  19. register int x = 0;
  20. register char ch = getchar();
  21. while(!isdigit(ch)) ch = getchar();
  22. while(isdigit(ch)) {
  23. x = x * 10 + ch - '0';
  24. ch = getchar();
  25. }
  26. return x;
  27. }
  28. inline void addEdge(int x, int y, int z) {
  29. e[++edge] = Edge(x, y, z);
  30. firstEdge[x] = edge;
  31. }
  32. bool getDepth() {
  33. std::queue <int> q;
  34. memset(depth, 0, sizeof(depth));
  35. depth[1] = 1;
  36. q.push(1);
  37. while(!q.empty()) {
  38. int from = q.front();
  39. q.pop();
  40. for(int k = firstEdge[from]; ~k; k = e[k].nxt) {
  41. int to = e[k].to, w = e[k].w;
  42. if(!depth[to] && w > 0) {
  43. depth[to] = depth[from] + 1;
  44. q.push(to);
  45. }
  46. }
  47. }
  48. return depth[n * m] > 0;
  49. }
  50. int Augment(int x, int flow) {
  51. if(x == n * m) return flow;
  52. for(int &k = curE[x]; ~k; k = e[k].nxt) {
  53. int to = e[k].to, w = e[k].w;
  54. if(depth[to] == depth[x] + 1 && w > 0) {
  55. int tmp = Augment(to, std::min(flow, w));
  56. if(tmp > 0) {
  57. e[k].w -= tmp;
  58. e[k ^ 1].w += tmp;
  59. return tmp;
  60. }
  61. }
  62. }
  63. return 0;
  64. }
  65. int Dinic() {
  66. int res = 0, tmp = 0;
  67. while(getDepth()) {
  68. for(int i = 1; i <= n * m; ++i) curE[i] = firstEdge[i];
  69. while((tmp = Augment(1, INF)) > 0) res += tmp;
  70. }
  71. return res;
  72. }
  73. int main() {
  74. n = read();
  75. m = read();
  76. memset(firstEdge, -1, sizeof(firstEdge));
  77. for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) id[i][j] = (i - 1) * m + j;
  78. for(int i = 1; i <= n; ++i) {
  79. for(int j = 1; j < m; ++j) {
  80. int v = read();
  81. addEdge(id[i][j], id[i][j + 1], v);
  82. addEdge(id[i][j + 1], id[i][j], v);
  83. }
  84. }
  85. for(int i = 1; i < n; ++i) {
  86. for(int j = 1; j <= m; ++j) {
  87. int v = read();
  88. addEdge(id[i][j], id[i + 1][j], v);
  89. addEdge(id[i + 1][j], id[i][j], v);
  90. }
  91. }
  92. for(int i = 1; i < n; ++i) {
  93. for(int j = 1; j < m; ++j) {
  94. int v = read();
  95. addEdge(id[i][j], id[i + 1][j + 1], v);
  96. addEdge(id[i + 1][j + 1], id[i][j], v);
  97. }
  98. }
  99. printf("%d\n", Dinic());
  100. return 0;
  101. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注