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

#include <bits/stdc++.h>

using namespace std;

#define int long long

template <typename flow_t = int, typename cost_t = int> struct mcSFlow {
  struct Edge {
    cost_t c;
    flow_t f;
    int to, rev;
    Edge(int _to, cost_t _c, flow_t _f, int _rev)
        : c(_c), f(_f), to(_to), rev(_rev) {}
  };
  static constexpr cost_t INFCOST = numeric_limits<cost_t>::max() / 2;
  cost_t eps;
  int N, S, T;
  vector<vector<Edge>> G;
  vector<int> isq, cur;
  vector<flow_t> ex;
  vector<cost_t> h;
  void init(int _N, int _S, int _T) {
    eps = 0;
    N = _N;
    S = _S;
    T = _T;
    G.resize(_N);
  }
  Edge add_edge(int a, int b, flow_t cap, cost_t cost) {
    assert(cap >= 0);
    assert(a >= 0 && a < N && b >= 0 && b < N);
    assert(a != b);
    cost *= N;
    eps = max(eps, abs(cost));
    G[a].emplace_back(b, cost, cap, G[b].size());
    Edge ret = G[a].back();
    G[b].emplace_back(a, -cost, 0, G[a].size() - 1);
    return ret;
  }
  void add_flow(Edge &e, flow_t f) {
    Edge &back = G[e.to][e.rev];
    if (!ex[e.to] && f)
      hs[h[e.to]].push_back(e.to);
    e.f -= f;
    ex[e.to] += f;
    back.f += f;
    ex[back.to] -= f;
  }
  vector<vector<int>> hs;
  vector<int> co;
  // fast max flow, lowest label version
  flow_t max_flow() {
    ex.assign(N, 0);
    h.assign(N, 0);
    hs.resize(2 * N);
    co.assign(2 * N, 0);
    cur.assign(N, 0);
    h[S] = N;
    ex[T] = 1;
    co[0] = N - 1;
    for (auto &e : G[S])
      add_flow(e, e.f);
    if (hs[0].size())
      for (int hi = 0; hi >= 0;) {
        int u = hs[hi].back();
        hs[hi].pop_back();
        while (ex[u] > 0) { // discharge u
          if (cur[u] == G[u].size()) {
            h[u] = 1e9;
            for (int i = 0; i < G[u].size(); ++i) {
              auto &e = G[u][i];
              if (e.f && h[u] > h[e.to] + 1) {
                h[u] = h[e.to] + 1;
                cur[u] = i;
              }
            }
            if (++co[h[u]], !--co[hi] && hi < N)
              for (int i = 0; i < N; ++i) {
                if (hi < h[i] && h[i] < N) {
                  --co[h[i]];
                  h[i] = N + 1;
                }
              }
            hi = h[u];
          } else if (G[u][cur[u]].f && h[u] == h[G[u][cur[u]].to] + 1) {
            add_flow(G[u][cur[u]], min(ex[u], G[u][cur[u]].f));
          } else
            ++cur[u];
        }
        while (hi >= 0 && hs[hi].empty())
          --hi;
      }
    return -ex[S];
  }
  // begin min cost flow
  bool look_ahead(int u) {
    if (ex[u])
      return false;
    cost_t newHeight = h[u] - N * eps;
    for (auto const &e : G[u]) {
      if (e.f == 0)
        continue;
      if (h[u] + e.c - h[e.to] < 0)
        return false; // outgoing admissible arc
      else
        newHeight = max(newHeight, h[e.to] - e.c); // try to make arc admissible
    }
    h[u] = newHeight - eps;
    return true;
  }
  void push(Edge &e, flow_t amt) {
    if (e.f < amt)
      amt = e.f;
    e.f -= amt;
    ex[e.to] += amt;
    G[e.to][e.rev].f += amt;
    ex[G[e.to][e.rev].to] -= amt;
  }
  void relabel(int vertex) {
    cost_t newHeight = -INFCOST;
    for (int i = 0; i < G[vertex].size(); ++i) {
      Edge const &e = G[vertex][i];
      if (e.f && newHeight < h[e.to] - e.c) {
        newHeight = h[e.to] - e.c;
        cur[vertex] = i;
      }
    }
    h[vertex] = newHeight - eps;
  }
  static constexpr int scale = 2;
  template <bool use_look_ahead = true> pair<flow_t, cost_t> minCostMaxFlow() {
    cost_t retCost = 0;
    for (int i = 0; i < N; ++i)
      for (Edge &e : G[i])
        retCost += e.c * (e.f);
    // remove this for circulation
    flow_t retFlow = max_flow();
    h.assign(N, 0);
    ex.assign(N, 0);
    isq.assign(N, 0);
    cur.assign(N, 0);
    stack<int> q;
    for (; eps; eps >>= scale) {
      fill(cur.begin(), cur.end(), 0);
      for (int i = 0; i < N; ++i)
        for (auto &e : G[i])
          if (h[i] + e.c - h[e.to] < 0 && e.f)
            push(e, e.f);
      for (int i = 0; i < N; ++i) {
        if (ex[i] > 0) {
          q.push(i);
          isq[i] = 1;
        }
      }
      while (!q.empty()) {
        int u = q.top();
        q.pop();
        isq[u] = 0;
        while (ex[u] > 0) {
          if (cur[u] == G[u].size())
            relabel(u);
          for (int &i = cur[u], max_i = G[u].size(); i < max_i; ++i) {
            Edge &e = G[u][i];
            if (e.f == 0)
              continue;
            if (h[u] + e.c - h[e.to] < 0) {
              if (use_look_ahead && look_ahead(e.to)) {
                --i;
                continue;
              }
              push(e, ex[u]);
              if (isq[e.to] == 0) {
                q.push(e.to);
                isq[e.to] = 1;
              }
              if (ex[u] == 0)
                break;
            }
          }
        }
      }
      if (eps > 1 && eps >> scale == 0) {
        eps = 1 << scale;
      }
    }
    for (int i = 0; i < N; ++i) {
      for (Edge &e : G[i]) {
        retCost -= e.c * (e.f);
      }
    }
    return make_pair(retFlow, retCost / 2 / N);
  }
  flow_t getFlow(Edge const &e) { return G[e.to][e.rev].f; }
};

const int N = 50 + 7;
int n;
int m;
int a[N][N];
bool vis[N][N];
vector<int> reach[N][N];

int id(int r, int c) { return c + (r - 1) * m - 1; }

void gol() {
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      vis[i][j] = 0;
    }
  }
}

int cnt;
int r;
int c;

mcSFlow<int, int> f;

void dfs(int i, int j) {
  vis[i][j] = 1;
  f.add_edge(1 + id(r, c), 1 + n * m + id(i, j), 1, -(i + j - r - c));
  if (a[i + 1][j] != -1 && !vis[i + 1][j]) {
    dfs(i + 1, j);
  }
  if (a[i][j + 1] != -1 && !vis[i][j + 1]) {
    dfs(i, j + 1);
  }
}

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

  int sum = 0;
  cin >> n >> m;
  f.init(1 + n * m + n * m + 1, 0, 1 + n * m + n * m);
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++) {
      a[i][j] = -1;
    }
  }
  for (int i = 1; i <= n; i++) {
    string s;
    cin >> s;
    for (int j = 1; j <= m; j++) {
      if (s[j - 1] == '.') {
        a[i][j] = 0;
      }
      if (s[j - 1] == 'o') {
        a[i][j] = 1;
      }
      if (s[j - 1] == '#') {
        a[i][j] = -1;
      }
    }
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      if (a[i][j] == 1) {
        r = i;
        c = j;
        cnt++;
        sum = i + j;
        gol();
        dfs(i, j);
        f.add_edge(0, 1 + id(i, j), 1, 0);
      }
    }
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      f.add_edge(1 + n * m + id(i, j), 1 + n * m + n * m, 1, 0);
    }
  }
  pair<int, int> it = f.minCostMaxFlow();
  cout << -it.second << "\\n";

  /// cout << f.minCostMaxFlow(0, 1 + n * m + n * m).second << "\\n";
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
template <typename flow_t = int, typename cost_t = int> struct mcSFlow {
  struct Edge {
    cost_t c;
    flow_t f;
    int to, rev;
    Edge(int _to, cost_t _c, flow_t _f, int _rev)
        : c(_c), f(_f), to(_to), rev(_rev) {}
  };
  static constexpr cost_t INFCOST = numeric_limits<cost_t>::max() / 2;
  cost_t eps;
  int N, S, T;
  vector<vector<Edge>> G;
  vector<int> isq, cur;
  vector<flow_t> ex;
  vector<cost_t> h;
  void init(int _N, int _S, int _T) {
    eps = 0;
    N = _N;
    S = _S;
    T = _T;
    G.resize(_N);
  }
  Edge add_edge(int a, int b, flow_t cap, cost_t cost) {
    assert(cap >= 0);
    assert(a >= 0 && a < N && b >= 0 && b < N);
    assert(a != b);
    cost *= N;
    eps = max(eps, abs(cost));
    G[a].emplace_back(b, cost, cap, G[b].size());
    Edge ret = G[a].back();
    G[b].emplace_back(a, -cost, 0, G[a].size() - 1);
    return ret;
  }
  void add_flow(Edge &e, flow_t f) {
    Edge &back = G[e.to][e.rev];
    if (!ex[e.to] && f)
      hs[h[e.to]].push_back(e.to);
    e.f -= f;
    ex[e.to] += f;
    back.f += f;
    ex[back.to] -= f;
  }
  vector<vector<int>> hs;
  vector<int> co;
  // fast max flow, lowest label version
  flow_t max_flow() {
    ex.assign(N, 0);
    h.assign(N, 0);
    hs.resize(2 * N);
    co.assign(2 * N, 0);
    cur.assign(N, 0);
    h[S] = N;
    ex[T] = 1;
    co[0] = N - 1;
    for (auto &e : G[S])
      add_flow(e, e.f);
    if (hs[0].size())
      for (int hi = 0; hi >= 0;) {
        int u = hs[hi].back();
        hs[hi].pop_back();
        while (ex[u] > 0) { // discharge u
          if (cur[u] == G[u].size()) {
            h[u] = 1e9;
            for (int i = 0; i < G[u].size(); ++i) {
              auto &e = G[u][i];
              if (e.f && h[u] > h[e.to] + 1) {
                h[u] = h[e.to] + 1;
                cur[u] = i;
              }
            }
            if (++co[h[u]], !--co[hi] && hi < N)
              for (int i = 0; i < N; ++i) {
                if (hi < h[i] && h[i] < N) {
                  --co[h[i]];
                  h[i] = N + 1;
                }
              }
            hi = h[u];
          } else if (G[u][cur[u]].f && h[u] == h[G[u][cur[u]].to] + 1) {
            add_flow(G[u][cur[u]], min(ex[u], G[u][cur[u]].f));
          } else
            ++cur[u];
        }
        while (hi >= 0 && hs[hi].empty())
          --hi;
      }
    return -ex[S];
  }
  // begin min cost flow
  bool look_ahead(int u) {
    if (ex[u])
      return false;
    cost_t newHeight = h[u] - N * eps;
    for (auto const &e : G[u]) {
      if (e.f == 0)
        continue;
      if (h[u] + e.c - h[e.to] < 0)
        return false; // outgoing admissible arc
      else
        newHeight = max(newHeight, h[e.to] - e.c); // try to make arc admissible
    }
    h[u] = newHeight - eps;
    return true;
  }
  void push(Edge &e, flow_t amt) {
    if (e.f < amt)
      amt = e.f;
    e.f -= amt;
    ex[e.to] += amt;
    G[e.to][e.rev].f += amt;
    ex[G[e.to][e.rev].to] -= amt;
  }
  void relabel(int vertex) {
    cost_t newHeight = -INFCOST;
    for (int i = 0; i < G[vertex].size(); ++i) {
      Edge const &e = G[vertex][i];
      if (e.f && newHeight < h[e.to] - e.c) {
        newHeight = h[e.to] - e.c;
        cur[vertex] = i;
      }
    }
    h[vertex] = newHeight - eps;
  }
  static constexpr int scale = 2;
  template <bool use_look_ahead = true> pair<flow_t, cost_t> minCostMaxFlow() {
    cost_t retCost = 0;
    for (int i = 0; i < N; ++i)
      for (Edge &e : G[i])
        retCost += e.c * (e.f);
    // remove this for circulation
    flow_t retFlow = max_flow();
    h.assign(N, 0);
    ex.assign(N, 0);
    isq.assign(N, 0);
    cur.assign(N, 0);
    stack<int> q;
    for (; eps; eps >>= scale) {
      fill(cur.begin(), cur.end(), 0);
      for (int i = 0; i < N; ++i)
        for (auto &e : G[i])
          if (h[i] + e.c - h[e.to] < 0 && e.f)
            push(e, e.f);
      for (int i = 0; i < N; ++i) {
        if (ex[i] > 0) {
          q.push(i);
          isq[i] = 1;
        }
      }
      while (!q.empty()) {
        int u = q.top();
        q.pop();
        isq[u] = 0;
        while (ex[u] > 0) {
          if (cur[u] == G[u].size())
            relabel(u);
          for (int &i = cur[u], max_i = G[u].size(); i < max_i; ++i) {
            Edge &e = G[u][i];
            if (e.f == 0)
              continue;
            if (h[u] + e.c - h[e.to] < 0) {
              if (use_look_ahead && look_ahead(e.to)) {
                --i;
                continue;
              }
              push(e, ex[u]);
              if (isq[e.to] == 0) {
                q.push(e.to);
                isq[e.to] = 1;
              }
              if (ex[u] == 0)
                break;
            }
          }
        }
      }
      if (eps > 1 && eps >> scale == 0) {
        eps = 1 << scale;
      }
    }
    for (int i = 0; i < N; ++i) {
      for (Edge &e : G[i]) {
        retCost -= e.c * (e.f);
      }
    }
    return make_pair(retFlow, retCost / 2 / N);
  }
  flow_t getFlow(Edge const &e) { return G[e.to][e.rev].f; }
};

const int N = 50 + 7;
int n;
int m;
int a[N][N];
bool vis[N][N];
vector<int> reach[N][N];

int id(int r, int c) { return c + (r - 1) * m - 1; }

void gol() {
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      vis[i][j] = 0;
    }
  }
}

int cnt;
int r;
int c;

mcSFlow<int, int> f;

void dfs(int i, int j) {
  vis[i][j] = 1;
  f.add_edge(1 + id(r, c), 1 + n * m + id(i, j), 1, -(i + j - r - c));
  if (a[i + 1][j] != -1 && !vis[i + 1][j]) {
    dfs(i + 1, j);
  }
  if (a[i][j + 1] != -1 && !vis[i][j + 1]) {
    dfs(i, j + 1);
  }
}

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);

  int sum = 0;
  cin >> n >> m;
  f.init(1 + n * m + n * m + 1, 0, 1 + n * m + n * m);
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++) {
      a[i][j] = -1;
    }
  }
  for (int i = 1; i <= n; i++) {
    string s;
    cin >> s;
    for (int j = 1; j <= m; j++) {
      if (s[j - 1] == '.') {
        a[i][j] = 0;
      }
      if (s[j - 1] == 'o') {
        a[i][j] = 1;
      }
      if (s[j - 1] == '#') {
        a[i][j] = -1;
      }
    }
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      if (a[i][j] == 1) {
        r = i;
        c = j;
        cnt++;
        sum = i + j;
        gol();
        dfs(i, j);
        f.add_edge(0, 1 + id(i, j), 1, 0);
      }
    }
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      f.add_edge(1 + n * m + id(i, j), 1 + n * m + n * m, 1, 0);
    }
  }
  pair<int, int> it = f.minCostMaxFlow();
  cout << -it.second << "\\n";

  /// cout << f.minCostMaxFlow(0, 1 + n * m + n * m).second << "\\n";
}