Problem p02542 (C++)

Buggy submission (status: Runtime Error):
#include <iostream>
#include <queue>
#include <vector>
#define INF 0x3f3f3f3f

using namespace std;

struct Edge {
  int u, v, c, w;
  Edge(int u, int v, int c, int w) : u(u), v(v), c(c), w(w) {}
};
class Graph {
  int n, s, t;
  vector<int> flow, dist, pre, last;
  vector<bool> vis;
  vector<Edge> edges;
  vector<vector<int>> adj;

public:
  Graph(int n, int s, int t) : n(n), s(s), t(t) {
    adj = vector<vector<int>>(n);
    flow.reserve(n);
    dist.reserve(n);
    pre.reserve(n);
    last.reserve(n);
    vis.reserve(n);
  }
  void add_edge(int u, int v, int c, int w) {
    int m = edges.size();
    edges.emplace_back(u, v, c, w);
    edges.emplace_back(v, u, 0, -w);
    adj[u].emplace_back(m);
    adj[v].emplace_back(m | 1);
  }

  bool spfa() {
    dist.assign(n, INF);
    flow.assign(n, INF);
    vis.assign(n, false);
    queue<int> q;
    q.push(s);
    vis[s] = true;
    dist[s] = 0;
    pre[t] = -1;

    while (!q.empty()) {
      int u = q.front();
      q.pop();
      vis[u] = false;
      for (int e : adj[u]) {
        auto [_, v, c, w] = edges[e];
        if (c > 0 && dist[v] > dist[u] + w) {
          dist[v] = dist[u] + w;
          pre[v] = u;
          last[v] = e;
          flow[v] = min(flow[u], c);
          if (!vis[v]) {
            vis[v] = true;
            q.push(v);
          }
        }
      }
    }

    return pre[t] != -1;
  }

  pair<int, int> min_cost_max_flow() {
    int mincost = 0;
    int maxflow = 0;
    while (spfa()) {
      int now = t;
      mincost += flow[t] * dist[t];
      while (now != s) {
        edges[last[now]].c -= flow[t];
        edges[last[now] ^ 1].c += flow[t];
        now = pre[now];
      }
      maxflow += flow[t];
    }
    return {maxflow, mincost};
  }
};

using namespace std;
int main() {
  int n, m;
  cin >> n >> m;
  vector<string> s(n);
  for (int i = 0; i < n; ++i)
    cin >> s[i];
  int ball = 0;
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < m; ++j)
      if (s[i][j] == 'o')
        ball++;
  int nodes = ball + n * m + 2;
  Graph g(nodes, 0, nodes - 1);
  int hi = n + m;
  for (int i = 1; i <= ball; ++i)
    g.add_edge(0, i, 1, 0);
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < m; ++j) {
      int idx = ball + i * m + j + 1;
      g.add_edge(idx, nodes - 1, 1, 0);
    }
  int ball_idx = 1;
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < m; ++j) {
      if (s[i][j] != 'o')
        continue;
      vector<vector<int>> dp(n, vector<int>(m, INF));
      dp[i][j] = 0;
      for (int p = i; p < n; ++p)
        for (int q = j; q < n; ++q) {
          if (s[p][q] == '#')
            continue;
          if (p > i && dp[p - 1][q] != INF)
            dp[p][q] = dp[p - 1][q] + 1;
          if (q > j && dp[p][q - 1] != INF)
            dp[p][q] = dp[p][q - 1] + 1;
          if (dp[p][q] != INF) {
            int idx = ball + p * m + q + 1;
            g.add_edge(ball_idx, idx, 1, hi - dp[p][q]);
          }
        }
      ball_idx++;
    }
  auto [flow, cost] = g.min_cost_max_flow();
  int ans = hi * flow - cost;
  cout << ans;
}

Fixed submission:
#include <iostream>
#include <queue>
#include <vector>
#define INF 0x3f3f3f3f

using namespace std;

struct Edge {
  int u, v, c, w;
  Edge(int u, int v, int c, int w) : u(u), v(v), c(c), w(w) {}
};
class Graph {
  int n, s, t;
  vector<int> flow, dist, pre, last;
  vector<bool> vis;
  vector<Edge> edges;
  vector<vector<int>> adj;

public:
  Graph(int n, int s, int t) : n(n), s(s), t(t) {
    adj = vector<vector<int>>(n);
    flow.reserve(n);
    dist.reserve(n);
    pre.reserve(n);
    last.reserve(n);
    vis.reserve(n);
  }
  void add_edge(int u, int v, int c, int w) {
    int m = edges.size();
    edges.emplace_back(u, v, c, w);
    edges.emplace_back(v, u, 0, -w);
    adj[u].emplace_back(m);
    adj[v].emplace_back(m | 1);
  }

  bool spfa() {
    dist.assign(n, INF);
    flow.assign(n, INF);
    vis.assign(n, false);
    queue<int> q;
    q.push(s);
    vis[s] = true;
    dist[s] = 0;
    pre[t] = -1;

    while (!q.empty()) {
      int u = q.front();
      q.pop();
      vis[u] = false;
      for (int e : adj[u]) {
        auto [_, v, c, w] = edges[e];
        if (c > 0 && dist[v] > dist[u] + w) {
          dist[v] = dist[u] + w;
          pre[v] = u;
          last[v] = e;
          flow[v] = min(flow[u], c);
          if (!vis[v]) {
            vis[v] = true;
            q.push(v);
          }
        }
      }
    }

    return pre[t] != -1;
  }

  pair<int, int> min_cost_max_flow() {
    int mincost = 0;
    int maxflow = 0;
    while (spfa()) {
      int now = t;
      mincost += flow[t] * dist[t];
      while (now != s) {
        edges[last[now]].c -= flow[t];
        edges[last[now] ^ 1].c += flow[t];
        now = pre[now];
      }
      maxflow += flow[t];
    }
    return {maxflow, mincost};
  }
};

using namespace std;
int main() {
  int n, m;
  cin >> n >> m;
  vector<string> s(n);
  for (int i = 0; i < n; ++i)
    cin >> s[i];
  int ball = 0;
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < m; ++j)
      if (s[i][j] == 'o')
        ball++;
  int nodes = ball + n * m + 2;
  Graph g(nodes, 0, nodes - 1);
  int hi = n + m;
  for (int i = 1; i <= ball; ++i)
    g.add_edge(0, i, 1, 0);
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < m; ++j) {
      int idx = ball + i * m + j + 1;
      g.add_edge(idx, nodes - 1, 1, 0);
    }
  int ball_idx = 1;
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < m; ++j) {
      if (s[i][j] != 'o')
        continue;
      vector<vector<int>> dp(n, vector<int>(m, INF));
      dp[i][j] = 0;
      for (int p = i; p < n; ++p)
        for (int q = j; q < m; ++q) {
          if (s[p][q] == '#')
            continue;
          if (p > i && dp[p - 1][q] != INF)
            dp[p][q] = dp[p - 1][q] + 1;
          if (q > j && dp[p][q - 1] != INF)
            dp[p][q] = dp[p][q - 1] + 1;
          if (dp[p][q] != INF) {
            int idx = ball + p * m + q + 1;
            g.add_edge(ball_idx, idx, 1, hi - dp[p][q]);
          }
        }
      ball_idx++;
    }
  auto [flow, cost] = g.min_cost_max_flow();
  int ans = hi * flow - cost;
  cout << ans;
}