fork download
  1. #include <cstdio>
  2. #include <vector>
  3. #include <queue>
  4. #include <limits>
  5. #include <algorithm>
  6. using namespace std;
  7. struct NetworkFlow {
  8. struct Edge {
  9. int target, inverse_index;
  10. int capacity, flow;
  11. Edge(int t, int c, int ii) : target(t), capacity(c), flow(0), inverse_index(ii) {}
  12. int residual() const { return capacity - flow; }
  13. };
  14. int V;
  15. vector< vector<Edge> > adj;
  16. vector<int> levels, edges_tried;
  17.  
  18. NetworkFlow(int V) : V(V), adj(V), levels(V), edges_tried(V) {}
  19.  
  20. void add_edge(int a, int b, int a2b, int b2a = 0) {
  21. int a2b_index = adj[a].size(), b2a_index = adj[b].size();
  22. adj[a].push_back(Edge(b, a2b, b2a_index));
  23. adj[b].push_back(Edge(a, b2a, a2b_index));
  24. }
  25.  
  26. bool assign_levels(int source, int sink) {
  27. fill(levels.begin(), levels.end(), -1);
  28. queue<int> q; q.push(source);
  29. levels[source] = 0;
  30. while (!q.empty()) {
  31. int here = q.front(); q.pop();
  32. for (int i = 0; i < adj[here].size(); ++i) {
  33. const Edge& e = adj[here][i];
  34. if (levels[e.target] == -1 && e.residual() > 0) {
  35. levels[e.target] = levels[here] + 1;
  36. q.push(e.target);
  37. }
  38. }
  39. }
  40. return levels[sink] != -1;
  41. }
  42.  
  43. int push_flow(int here, int sink, int flow) {
  44. if (here == sink) return flow;
  45.  
  46. for (int& i = edges_tried[here]; i < adj[here].size(); ++i) {
  47. Edge& e = adj[here][i];
  48. if (e.residual() > 0 && levels[e.target] == levels[here] + 1) {
  49. int amt = push_flow(e.target, sink, min(flow, e.residual()));
  50. if (amt > 0) {
  51. Edge& e_inv = adj[e.target][e.inverse_index];
  52. e.flow += amt;
  53. e_inv.flow = -e.flow;
  54. return amt;
  55. }
  56. }
  57. }
  58. return 0;
  59. }
  60.  
  61. int go(int source, int sink) {
  62. int total_flow = 0;
  63. while (assign_levels(source, sink)) {
  64. fill(edges_tried.begin(), edges_tried.end(), 0);
  65. while (true) {
  66. int pushed = push_flow(source, sink, numeric_limits<int>::max());
  67. if (pushed == 0) break;
  68. total_flow += pushed;
  69. }
  70. }
  71. return total_flow;
  72. }
  73. };
  74. int a[111][111], rn, M, row[111][111], col[111][111];
  75. int main() {
  76. int n, m;
  77. scanf("%d%d", &n, &m);
  78. for (int i = 1; i <= n; i++) {
  79. for (int j = 1; j <= m; j++) {
  80. scanf("%d", &a[i][j]);
  81. if (a[i][j] != 2) {
  82. if (row[i][j - 1]) row[i][j] = row[i][j - 1];
  83. else row[i][j] = ++M;
  84. }
  85. }
  86. }
  87. rn = M;
  88. for (int j = 1; j <= m; j++) {
  89. for (int i = 1; i <= n; i++) {
  90. if (a[i][j] != 2) {
  91. if (col[i - 1][j]) col[i][j] = col[i - 1][j];
  92. else col[i][j] = ++M;
  93. }
  94. }
  95. }
  96. NetworkFlow f(M + 2);
  97. for (int i = 1; i <= rn; i++) f.add_edge(0, i, 1, 0);
  98. for (int i = rn + 1; i <= M; i++) f.add_edge(i, M + 1, 1, 0);
  99. for (int i = 1; i <= n; i++) {
  100. for (int j = 1; j <= m; j++) {
  101. if (a[i][j] == 0) {
  102. f.add_edge(row[i][j], col[i][j], 1, 0);
  103. }
  104. }
  105. }
  106. printf("%d", f.go(0, M + 1));
  107. }
Success #stdin #stdout 0s 3628KB
stdin
3 4
2 0 0 0
2 2 2 1
0 1 0 2
stdout
2