Problem p02542 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>/
// #include <ext/pb_ds/tree_policy.hpp>

#define pb push_back
#define mp make_pair
#define PI (acos(-1.0))
#define IN freopen("nocross.in", "r", stdin)
#define OUT freopen("nocross.out", "w", stdout)
#define FOR(i, a, b) for (i = a; i <= b; i++)
#define DBG printf("Hi\n")
#define i64 long long int
#define eps (1e-8)
#define xx first
#define yy second
#define ln 17
#define off 2
#define SZ(z) ((int)z.size())

#define FastIO                                                                 \
  ios_base::sync_with_stdio(false);                                            \
  cin.tie(NULL)

// using namespace __gnu_pbds;
using namespace std;

// typedef tree< i64, null_type, less<i64>, rb_tree_tag,
// tree_order_statistics_node_update> ordered_set;

// #define maxn 1000005
// #define INF 2000000000000000000LL
// #define mod 998244353LL

namespace mcmf {
// this should be at least 2*( added edge in the graph )
const int MAX = 31000;
const long long INF = 1LL << 60;

long long cap[MAX], flow[MAX], cost[MAX], dis[MAX];
int n, m, s, t, Q[MAX * 10], adj[MAX], link[MAX], last[MAX], from[MAX],
    visited[MAX];

void init(int nodes, int source, int sink) {
  m = 0, n = nodes, s = source, t = sink;
  for (int i = 0; i <= n; i++)
    last[i] = -1;
}

void addEdge(int u, int v, long long c, long long w) {
  adj[m] = v, cap[m] = c, flow[m] = 0, cost[m] = +w, link[m] = last[u],
  last[u] = m++;
  adj[m] = u, cap[m] = 0, flow[m] = 0, cost[m] = -w, link[m] = last[v],
  last[v] = m++;
}

bool spfa() {
  int i, j, x, f = 0, l = 0;
  for (i = 0; i <= n; i++)
    visited[i] = 0, dis[i] = INF;

  dis[s] = 0, Q[l++] = s;
  while (f < l) {
    i = Q[f++];
    for (j = last[i]; j != -1; j = link[j]) {
      if (flow[j] < cap[j]) {
        x = adj[j];
        if (dis[x] > dis[i] + cost[j]) {
          dis[x] = dis[i] + cost[j], from[x] = j;
          if (!visited[x]) {
            visited[x] = 1;
            if (f && rand() & 7)
              Q[--f] = x;
            else
              Q[l++] = x;
          }
        }
      }
    }
    visited[i] = 0;
  }
  return (dis[t] != INF);
}

pair<long long, long long> solve() {
  int i, j;
  long long mincost = 0, maxflow = 0;

  while (spfa()) {
    long long aug = INF;
    for (i = t, j = from[i]; i != s; i = adj[j ^ 1], j = from[i]) {
      aug = min(aug, cap[j] - flow[j]);
    }
    for (i = t, j = from[i]; i != s; i = adj[j ^ 1], j = from[i]) {
      flow[j] += aug, flow[j ^ 1] -= aug;
    }
    maxflow += aug, mincost += aug * dis[t];
  }
  return make_pair(mincost, maxflow);
}
} // namespace mcmf

int dp[55][55][55][55];
char s[55][55];
int cnt[55][55];

int main() {
  int n, m;
  scanf("%d %d", &n, &m);

  for (int i = 0; i < n; i++) {
    scanf("%s", s[i]);
  }

  for (int i = n - 1; i >= 0; i--) {
    for (int j = m - 1; j >= 0; j--) {
      if (s[i][j] == '#')
        continue;
      dp[i][j][i][j] = 1;

      if (i < n - 1) {
        for (int k = 0; k < n; k++) {
          for (int l = 0; l < m; l++)
            dp[i][j][k][l] |= dp[i + 1][j][k][l];
        }
      }
      if (j < m - 1) {
        for (int k = 0; k < n; k++) {
          for (int l = 0; l < m; l++)
            dp[i][j][k][l] |= dp[i][j + 1][k][l];
        }
      }
    }
  }

  int cntob = 0;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++)
      if (s[i][j] == 'o')
        cnt[i][j] = cntob++;
  }

  int src = cntob + n * m, sink = cntob + n * m + 1;

  mcmf::init(cntob + n * m + 2, src, sink);

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (s[i][j] != 'o')
        continue;

      for (int k = 0; k < n; k++) {
        for (int l = 0; l < m; l++) {
          if (dp[i][j][k][l])
            mcmf::addEdge(cnt[i][j], cntob + k * m + l, 1,
                          -((k + l) - (i + j)));
        }
      }
    }
  }

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (s[i][j] == 'o')
        mcmf::addEdge(src, cnt[i][j], 1, 0);
      if (s[i][j] != '#')
        mcmf::addEdge(cntob + i * m + j, sink, 1, 0);
    }
  }

  pair<int, int> ans = mcmf::solve();

  printf("%d\n", -ans.xx);

  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>/
// #include <ext/pb_ds/tree_policy.hpp>

#define pb push_back
#define mp make_pair
#define PI (acos(-1.0))
#define IN freopen("nocross.in", "r", stdin)
#define OUT freopen("nocross.out", "w", stdout)
#define FOR(i, a, b) for (i = a; i <= b; i++)
#define DBG printf("Hi\n")
#define i64 long long int
#define eps (1e-8)
#define xx first
#define yy second
#define ln 17
#define off 2
#define SZ(z) ((int)z.size())

#define FastIO                                                                 \
  ios_base::sync_with_stdio(false);                                            \
  cin.tie(NULL)

// using namespace __gnu_pbds;
using namespace std;

// typedef tree< i64, null_type, less<i64>, rb_tree_tag,
// tree_order_statistics_node_update> ordered_set;

// #define maxn 1000005
// #define INF 2000000000000000000LL
// #define mod 998244353LL

namespace mcmf {
// this should be at least 2*( added edge in the graph )
const int MAX = 500000;
const long long INF = 1LL << 60;

long long cap[MAX], flow[MAX], cost[MAX], dis[MAX];
int n, m, s, t, Q[MAX * 10], adj[MAX], link[MAX], last[MAX], from[MAX],
    visited[MAX];

void init(int nodes, int source, int sink) {
  m = 0, n = nodes, s = source, t = sink;
  for (int i = 0; i <= n; i++)
    last[i] = -1;
}

void addEdge(int u, int v, long long c, long long w) {
  adj[m] = v, cap[m] = c, flow[m] = 0, cost[m] = +w, link[m] = last[u],
  last[u] = m++;
  adj[m] = u, cap[m] = 0, flow[m] = 0, cost[m] = -w, link[m] = last[v],
  last[v] = m++;
}

bool spfa() {
  int i, j, x, f = 0, l = 0;
  for (i = 0; i <= n; i++)
    visited[i] = 0, dis[i] = INF;

  dis[s] = 0, Q[l++] = s;
  while (f < l) {
    i = Q[f++];
    for (j = last[i]; j != -1; j = link[j]) {
      if (flow[j] < cap[j]) {
        x = adj[j];
        if (dis[x] > dis[i] + cost[j]) {
          dis[x] = dis[i] + cost[j], from[x] = j;
          if (!visited[x]) {
            visited[x] = 1;
            if (f && rand() & 7)
              Q[--f] = x;
            else
              Q[l++] = x;
          }
        }
      }
    }
    visited[i] = 0;
  }
  return (dis[t] != INF);
}

pair<long long, long long> solve() {
  int i, j;
  long long mincost = 0, maxflow = 0;

  while (spfa()) {
    long long aug = INF;
    for (i = t, j = from[i]; i != s; i = adj[j ^ 1], j = from[i]) {
      aug = min(aug, cap[j] - flow[j]);
    }
    for (i = t, j = from[i]; i != s; i = adj[j ^ 1], j = from[i]) {
      flow[j] += aug, flow[j ^ 1] -= aug;
    }
    maxflow += aug, mincost += aug * dis[t];
  }
  return make_pair(mincost, maxflow);
}
} // namespace mcmf

int dp[55][55][55][55];
char s[55][55];
int cnt[55][55];

int main() {
  int n, m;
  scanf("%d %d", &n, &m);

  for (int i = 0; i < n; i++) {
    scanf("%s", s[i]);
  }

  for (int i = n - 1; i >= 0; i--) {
    for (int j = m - 1; j >= 0; j--) {
      if (s[i][j] == '#')
        continue;
      dp[i][j][i][j] = 1;

      if (i < n - 1) {
        for (int k = 0; k < n; k++) {
          for (int l = 0; l < m; l++)
            dp[i][j][k][l] |= dp[i + 1][j][k][l];
        }
      }
      if (j < m - 1) {
        for (int k = 0; k < n; k++) {
          for (int l = 0; l < m; l++)
            dp[i][j][k][l] |= dp[i][j + 1][k][l];
        }
      }
    }
  }

  int cntob = 0;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++)
      if (s[i][j] == 'o')
        cnt[i][j] = cntob++;
  }

  int src = cntob + n * m, sink = cntob + n * m + 1;

  mcmf::init(cntob + n * m + 2, src, sink);

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (s[i][j] != 'o')
        continue;

      for (int k = 0; k < n; k++) {
        for (int l = 0; l < m; l++) {
          if (dp[i][j][k][l])
            mcmf::addEdge(cnt[i][j], cntob + k * m + l, 1,
                          -((k + l) - (i + j)));
        }
      }
    }
  }

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (s[i][j] == 'o')
        mcmf::addEdge(src, cnt[i][j], 1, 0);
      if (s[i][j] != '#')
        mcmf::addEdge(cntob + i * m + j, sink, 1, 0);
    }
  }

  pair<int, int> ans = mcmf::solve();

  printf("%d\n", -ans.xx);

  return 0;
}