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

#include <bits/stdc++.h>
#pragma GCC optimization("Ofast")
#pragma GCC optimization("unroll-loops")
using namespace std;
#define int long long
#define rep(i, n) for (int i = 0; i < n; i++)
#define REP(i, n) for (int i = 1; i < n; i++)
#define rev(i, n) for (int i = n - 1; i >= 0; i--)
#define all(v) v.begin(), v.end()
#define P pair<int, int>
#define len(s) (int)s.size()

template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
constexpr int mod = 1e9 + 7;
constexpr long long inf = 3e18;
struct PrimalDual {
  struct edge {
    int to, cap, cost, rev;
  };
  vector<vector<edge>> graph;
  bool negative = false;
  void add_edge(int from, int to, int cap, int cost) {
    graph[from].push_back({to, cap, cost, len(graph[to])});
    graph[to].push_back({from, 0ll, -cost, len(graph[from]) - 1});
    if (cost < 0)
      negative = true;
  }
  int minCostFlow(int s, int t, int f) {
    int V = len(graph);
    vector<int> potential(V), minCost, prevv(V, -1), preve(V, -1);
    int res = 0;
    if (negative) {
      minCost.assign(V, inf);
      minCost[s] = 0;
      rep(_, V - 1) {
        rep(i, V) {
          rep(j, len(graph[i])) {
            edge &e = graph[i][j];
            if (e.cap > 0 &&
                chmin(minCost[e.to],
                      minCost[i] + e.cost + potential[i] - potential[e.to])) {
              prevv[e.to] = i;
              preve[e.to] = j;
            }
          }
        }
      }
      if (minCost[t] == inf)
        return -1;
      rep(i, V) potential[i] += minCost[i];
      for (int i = t; i != s; i = prevv[i]) {
        graph[prevv[i]][preve[i]].cap--;
        graph[i][graph[prevv[i]][preve[i]].rev].cap++;
      }
      res += potential[t];
    }
    vector<bool> used(V);
    while (f > 0) {
      minCost.assign(V, inf);
      used.assign(V, 0);
      minCost[s] = 0;
      priority_queue<P, vector<P>, greater<>> que;
      que.push({0, s});
      while (!que.empty()) {
        P p = que.top();
        que.pop();
        if (minCost[p.second] < p.first)
          continue;
        rep(i, len(graph[p.second])) {
          edge &e = graph[p.second][i];
          if (e.cap > 0 &&
              chmin(minCost[e.to],
                    p.first + e.cost + potential[p.second] - potential[e.to])) {
            prevv[e.to] = p.second;
            preve[e.to] = i;
            que.push({minCost[e.to], e.to});
          }
        }
      }

      if (minCost[t] == inf)
        return -1;
      rep(i, V) potential[i] += minCost[i];
      int addflow = f;
      for (int i = t; i != s; i = prevv[i])
        chmin(addflow, graph[prevv[i]][preve[i]].cap);
      f -= addflow;
      res += addflow * potential[t];
      for (int i = t; i != s; i = prevv[i]) {
        edge &e = graph[prevv[i]][preve[i]];
        e.cap -= addflow;
        graph[i][e.rev].cap += addflow;
      }
    }
    return res;
  }
  PrimalDual(int V) : graph(V){};
};

int N, M;
char c[55][55];
bool used[55][55];
signed main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cin >> N >> M;
  rep(i, N) rep(j, M) cin >> c[i][j];
  PrimalDual F(N * M + 2);
  int cnt = 0;
  rep(i, N) rep(j, M) {
    if (c[i][j] == 'o') {
      cnt++;
      memset(used, 0, sizeof(used));
      F.add_edge(N * M, i * M + j, 1, 0);
      F.add_edge(i * M + j, N * M + 1, 1, mod);
      used[i][j] = true;
      rep(k, N) rep(l, M) {
        if ((k != i || l != j) && used[k][l]) {
          F.add_edge(i * M + j, k * M + l, 1, mod - (k - i + l - j));
        }
        if (c[k + 1][l] != '#')
          used[k + 1][l] |= used[k][l];
        if (c[k][l + 1] != '#')
          used[k][l + 1] |= used[k][l];
      }
    } else
      F.add_edge(i * M + j, N * M + 1, 1, 0);
  }
  cout << cnt * mod - F.minCostFlow(N * M, N * M + 1, cnt) << "\\n";
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
// #pragma GCC optimization ("Ofast")
// #pragma GCC optimization ("unroll-loops")
using namespace std;
#define int long long
#define rep(i, n) for (int i = 0; i < n; i++)
#define REP(i, n) for (int i = 1; i < n; i++)
#define rev(i, n) for (int i = n - 1; i >= 0; i--)
#define all(v) v.begin(), v.end()
#define P pair<int, int>
#define len(s) (int)s.size()

template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
constexpr int mod = 1e9 + 7;
constexpr long long inf = 3e18;
struct PrimalDual {
  struct edge {
    int to, cap, cost, rev;
  };
  vector<vector<edge>> graph;
  void add_edge(int from, int to, int cap, int cost) {
    graph[from].push_back({to, cap, cost, len(graph[to])});
    graph[to].push_back({from, 0ll, -cost, len(graph[from]) - 1});
  }
  int minCostFlow(int s, int t, int f) {
    int V = len(graph);
    vector<int> potential(V), minCost, prevv(V, -1), preve(V, -1);
    vector<bool> used(V);
    int res = 0;
    while (f > 0) {
      minCost.assign(V, inf);
      used.assign(V, 0);
      minCost[s] = 0;
      rep(_, V - 1) {
        int mn = inf, idx;
        rep(i, V) if (!used[i] && chmin(mn, minCost[i])) idx = i;
        used[idx] = true;
        rep(i, len(graph[idx])) {
          edge &e = graph[idx][i];
          int nextcost = mn + e.cost + potential[idx] - potential[e.to];
          if (e.cap > 0 && minCost[e.to] > nextcost) {
            minCost[e.to] = nextcost;
            prevv[e.to] = idx;
            preve[e.to] = i;
          }
        }
      }
      if (minCost[t] == inf)
        return -1;
      rep(i, V) potential[i] += minCost[i];
      int addflow = f;
      for (int i = t; i != s; i = prevv[i])
        chmin(addflow, graph[prevv[i]][preve[i]].cap);
      f -= addflow;
      res += addflow * potential[t];
      for (int i = t; i != s; i = prevv[i]) {
        edge &e = graph[prevv[i]][preve[i]];
        e.cap -= addflow;
        graph[i][e.rev].cap += addflow;
      }
    }
    return res;
  }
  PrimalDual(int V) : graph(V){};
};

int N, M;
char c[55][55];
bool used[55][55];
signed main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cin >> N >> M;
  rep(i, N) rep(j, M) cin >> c[i][j];
  PrimalDual F(N * M + 2);
  int cnt = 0;
  rep(i, N) rep(j, M) {
    if (c[i][j] == 'o') {
      cnt++;
      memset(used, 0, sizeof(used));
      F.add_edge(N * M, i * M + j, 1, 0);
      F.add_edge(i * M + j, N * M + 1, 1, mod);
      used[i][j] = true;
      rep(k, N) rep(l, M) {
        if ((k != i || l != j) && used[k][l]) {
          F.add_edge(i * M + j, k * M + l, 1, mod - (k - i + l - j));
        }
        if (c[k + 1][l] != '#')
          used[k + 1][l] |= used[k][l];
        if (c[k][l + 1] != '#')
          used[k][l + 1] |= used[k][l];
      }
    } else
      F.add_edge(i * M + j, N * M + 1, 1, 0);
  }
  cout << cnt * mod - F.minCostFlow(N * M, N * M + 1, cnt) << "\\n";
}