Problem p02542 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
#define LL long long
#define PII pair<int, int>
#define PLL pair<LL, LL>
#define all_of(v) (v).begin(), (v).end()
#define sort_unique(c)                                                         \\
  (sort(c.begin(), c.end()),                                                   \\
   c.resize(distance(c.begin(), unique(c.begin(), c.end()))))
#define fi first
#define se second
// const LL INF = (LL) 1e9 + 8763;
// const LL MOD = (LL) 1e9 + 7;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
// #define int LL
const int MAXV = 2505;
const int INF = 1e8;

struct Min_cost_flow {
// 0-based
#define fi first
#define se second
  struct Edge {
    int to, cap;
    int cost, rev;
  };

  int V, E;
  vector<Edge> G[MAXV];
  PII pre[MAXV];
  int flow[MAXV], dist[MAXV];
  bool inque[MAXV];

  void init(int _V) {
    V = _V;
    for (int i = 0; i <= V; i++)
      G[i].clear();
  }
  PII add_edge(int fr, int to, int cap, int cost) {
    int a = G[fr].size(), b = G[to].size();
    G[fr].push_back({to, cap, cost, b});
    G[to].push_back({fr, 0, -cost, a});
    return {fr, (int)G[fr].size() - 1};
  }
  bool SPFA(int s, int t, int &ans_flow, int &ans_cost) {
    queue<int> que;
    for (int i = 0; i <= V; i++) {
      dist[i] = INF;
      inque[i] = false;
    }
    dist[s] = 0;
    flow[s] = INF;
    inque[s] = true;
    que.push(s);
    while (!que.empty()) {
      int v = que.front();
      que.pop();
      inque[v] = false;
      for (int i = 0; i < G[v].size(); i++) {
        const Edge &e = G[v][i];
        if (e.cap > 0 && dist[v] + e.cost < dist[e.to]) {
          flow[e.to] = min(flow[v], e.cap);
          dist[e.to] = dist[v] + e.cost;
          pre[e.to] = {v, i};
          if (!inque[e.to])
            que.push(e.to), inque[e.to] = true;
        }
      }
    }
    if (dist[t] == INF)
      return false;
    // if (dist[t]>=0) return false;
    //  Add above line -> min cost first, then max flow (priority)
    //  Without        -> max flow first, then min cost

    int v = t, f = flow[t];
    ans_flow += flow[t];
    ans_cost += (dist[t] * flow[t]);
    while (v != s) {
      Edge &e = G[pre[v].fi][pre[v].se];
      e.cap -= f;
      G[v][e.rev].cap += f;
      v = pre[v].fi;
    }
    return true;
  }
  pair<int, int> mcmf(int s, int t) {
    int ans_flow = 0, ans_cost = 0;
    while (SPFA(s, t, ans_flow, ans_cost))
      ;
    return make_pair(ans_flow, ans_cost);
  }
} algo;

const int MAXN = 55;
int n, m, vis[MAXN][MAXN];
char mp[MAXN][MAXN];

void solve() {
  cin >> n >> m;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      cin >> mp[i][j];
    }
  }

  int src = n * m, tgt = src + 1;
  algo.init(tgt + 1);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (mp[i][j] == 'o') {
        algo.add_edge(src, i * m + j, 1, 0);
      }
      if (mp[i][j] != '#') {
        if (i != n - 1 && mp[i + 1][j] != '#') {
          algo.add_edge(i * m + j, (i + 1) * m + j, INF, -1);
        }
        if (j != m - 1 && mp[i][j + 1] != '#') {
          algo.add_edge(i * m + j, i * m + (j + 1), INF, -1);
        }
        algo.add_edge(i * m + j, tgt, 1, 0);
      }
    }
  }

  auto res = algo.mcmf(src, tgt);
  //	cout << "Flow " << res.fi << '\\n';
  cout << -res.se << '\\n';
}

signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);

  int tc = 1;
  //	cin >> tc;
  for (int i = 1; i <= tc; i++) {
    solve();
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#define LL long long
#define PII pair<int, int>
#define PLL pair<LL, LL>
#define all_of(v) (v).begin(), (v).end()
#define sort_unique(c)                                                         \\
  (sort(c.begin(), c.end()),                                                   \\
   c.resize(distance(c.begin(), unique(c.begin(), c.end()))))
#define fi first
#define se second
// const LL INF = (LL) 1e9 + 8763;
// const LL MOD = (LL) 1e9 + 7;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
// #define int LL
const int INF = 20000; // LL

struct KM {
  // Maximum Bipartite Weighted Matching (Perfect Match)
  static const int MXN = 2505;
  int n, match[MXN], vx[MXN], vy[MXN];
  int edge[MXN][MXN], lx[MXN], ly[MXN], slack[MXN];
  // ^^^^ LL
  void init(int _n) {
    n = _n;
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++)
        edge[i][j] = 0;
  }
  void addEdge(int x, int y, int w) // LL
  {
    edge[x][y] = w;
  }
  bool DFS(int x) {
    vx[x] = 1;
    for (int y = 0; y < n; y++) {
      if (vy[y])
        continue;
      if (lx[x] + ly[y] > edge[x][y]) {
        slack[y] = min(slack[y], lx[x] + ly[y] - edge[x][y]);
      } else {
        vy[y] = 1;
        if (match[y] == -1 || DFS(match[y])) {
          match[y] = x;
          return true;
        }
      }
    }
    return false;
  }
  int solve() {
    fill(match, match + n, -1);
    fill(lx, lx + n, -INF);
    fill(ly, ly + n, 0);
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++)
        lx[i] = max(lx[i], edge[i][j]);
    for (int i = 0; i < n; i++) {
      fill(slack, slack + n, INF);
      while (true) {
        fill(vx, vx + n, 0);
        fill(vy, vy + n, 0);
        if (DFS(i))
          break;
        int d = INF; // long long
        for (int j = 0; j < n; j++)
          if (!vy[j])
            d = min(d, slack[j]);
        for (int j = 0; j < n; j++) {
          if (vx[j])
            lx[j] -= d;
          if (vy[j])
            ly[j] += d;
          else
            slack[j] -= d;
        }
      }
    }
    int res = 0;
    for (int i = 0; i < n; i++)
      res += edge[match[i]][i];
    return res;
  }
} km;

const int MAXN = 55;
int n, m, vis[MAXN][MAXN];
char mp[MAXN][MAXN];

void dfs(int r, int c, int fr, int fc) {
  vis[r][c] = 1;
  km.addEdge(fr * m + fc, r * m + c, (r - fr) + (c - fc));
  if (r != n - 1 && mp[r + 1][c] != '#') {
    dfs(r + 1, c, fr, fc);
  }
  if (c != m - 1 && mp[r][c + 1] != '#') {
    dfs(r, c + 1, fr, fc);
  }
}

void solve() {
  cin >> n >> m;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      cin >> mp[i][j];
    }
  }

  km.init(n * m);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (mp[i][j] == 'o') {
        memset(vis, 0, sizeof(vis));
        dfs(i, j, i, j);
        for (int k = 0; k < n; k++) {
          for (int l = 0; l < m; l++) {
            if (!vis[k][l]) {
              km.addEdge(i * m + j, k * m + l, -INF);
            }
          }
        }
      }
    }
  }

  cout << km.solve() << '\\n';
}

signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);

  int tc = 1;
  //	cin >> tc;
  for (int i = 1; i <= tc; i++) {
    solve();
  }

  return 0;
}