[关闭]
@ZCDHJ 2018-09-28T13:50:19.000000Z 字数 1927 阅读 684

POJ3422 Kaka's Matrix Travels

网络流


Vjudge

费用流模板题。

将每个点拆成一个入点和一个出点,在入点与出点间连一条容量为 ,费用为点权的边,再连一条容量为 ,费用为 的边。然后再在相邻的点之间连边就行了。然后直接跑最大费用最大流。

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