Problem p03718 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>

using flow_type = int;

struct dinic {
  struct edge {
    int src, dst;
    flow_type cap, flow;
    edge *next, *rev;

    flow_type residue() const { return cap - flow; }

    void *operator new(std::size_t) {
      constexpr std::size_t MAX_E = 1000010;
      static edge pool[MAX_E];
      static std::size_t p = 0;
      return pool + p++;
    }
  };
  int n, source, sink;
  edge **g;
  int *level, *queue;
  edge **prog;

  dinic(int n_ = 0)
      : n(n_), g(new edge *[n]()), level(new int[n]), queue(new int[n]),
        prog(new edge *[n]) {}

  ~dinic() {
    delete[] g;
    delete[] level;
    delete[] queue;
    delete[] prog;
  }

  flow_type maximum_flow(int source_, int sink_) {
    source = source_;
    sink = sink_;
    flow_type res = 0;
    while (levelize()) {
      std::copy(g, g + n, prog);
      res += augment(source, std::numeric_limits<flow_type>::max());
    }
    return res;
  }

  edge *add_edge1(int u, int v, flow_type c, flow_type f) {
    return g[u] = new edge{u, v, c, f, g[u], nullptr};
  }

  std::pair<edge *, edge *> add_edge(int u, int v, flow_type c) {
    if (u == v || c == 0)
      return {nullptr, nullptr};
    auto uv = add_edge1(u, v, c, 0);
    auto vu = add_edge1(v, u, c, c);
    uv->rev = vu;
    vu->rev = uv;
    return {uv, vu};
  }

  bool levelize() {
    int fst = 0, lst = 0;
    queue[lst++] = source;
    std::fill(level, level + n, -1);
    level[source] = 0;
    while (fst != lst) {
      int v = queue[fst++];
      if (v == sink)
        break;
      for (auto e = g[v]; e != nullptr; e = e->next) {
        if (level[e->dst] == -1 && e->residue() != 0) {
          level[e->dst] = level[v] + 1;
          queue[lst++] = e->dst;
        }
      }
    }
    return level[sink] != -1;
  }

  flow_type augment(int v, flow_type lim) {
    flow_type res = 0;
    if (v == sink)
      return lim;
    for (auto &e = prog[v]; e; e = e->next) {
      if (lim == 0)
        break;
      if (level[v] < level[e->dst] && e->residue() != 0) {
        flow_type aug = augment(e->dst, std::min(lim, e->residue()));
        if (aug == 0)
          continue;
        e->flow += aug;
        e->rev->flow -= aug;
        res += aug;
        lim -= aug;
      }
    }
    return res;
  }
};

using namespace std;

// int main() {
//     int N, M;
//     cin >> N >> M;
//     dinic g(N);
//     while (M--) {
//         int a, b, c;
//         cin >> a >> b >> c;
//         g.add_edge(a, b, c);
//     }
//     cout << g.maximum_flow(0, N - 1) << endl;
// }
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define FOR(i, a, b) for (int i = (a); i < int(b); ++i)
#define RFOR(i, a, b) for (int i = (b)-1; i >= int(a); --i)
#define rep(i, n) FOR(i, 0, n)
#define rep1(i, n) FOR(i, 1, int(n) + 1)
#define rrep(i, n) RFOR(i, 0, n)
#define rrep1(i, n) RFOR(i, 1, int(n) + 1)
#define all(c) begin(c), end(c)
const int MOD = 1000000007;

const int INF = 1e6;

signed main() {
  int h, w;
  while (cin >> h >> w && h) {
    vector<string> g(h);

    rep(i, h) { cin >> g[i]; }
    dinic dn(h * w * 2);
    rep(i, h) {
      rep(j1, w) rep(j2, w) if (j1 != j2) {
        if (g[i][j1] != '.' && g[i][j2] != '.') {
          int u = i * w + j1;
          int v = i * w + j2 + h * w;
          dn.add_edge(u, v, INF);
        }
      }
    }
    rep(j, w) {
      rep(i1, h) rep(i2, h) if (i1 != i2) {
        if (g[i1][j] != '.' && g[i2][j] != '.') {
          int u = i1 * w + j;
          int v = i2 * w + j + h * w;
          dn.add_edge(u, v, INF);
        }
      }
    }

    rep(i, h) rep(j, w) {
      if (g[i][j] != '.') {
        int cost;
        if (g[i][j] == 'S' || g[i][j] == 'T') {
          cost = INF;
        } else {
          cost = 1;
        }
        int u = i * w + j;
        int v = i * w + j + h * w;
        dn.add_edge(v, u, cost);
      }
    }

    int si = -1, sj = -1, ti = -1, tj = -1;
    rep(i, h) rep(j, w) {
      if (g[i][j] == 'S')
        si = i, sj = j;
      if (g[i][j] == 'T')
        ti = i, tj = j;
    }
    // dump(si*w + sj, ti*w + tj + h*w);
    if (si == ti || sj == tj) {
      cout << -1;
    } else {
      cout << dn.maximum_flow(si * w + sj, ti * w + tj + h * w);
    }
    cout << endl;
    // dn.show();
  }
}


Fixed submission:
#include <bits/stdc++.h>

using flow_type = int;

struct dinic {
  struct edge {
    int src, dst;
    flow_type cap, flow;
    edge *next, *rev;

    flow_type residue() const { return cap - flow; }

    void *operator new(std::size_t) {
      constexpr std::size_t MAX_E = 5000010;
      static edge pool[MAX_E];
      static std::size_t p = 0;
      return pool + p++;
    }
  };
  int n, source, sink;
  edge **g;
  int *level, *queue;
  edge **prog;

  dinic(int n_ = 0)
      : n(n_), g(new edge *[n]()), level(new int[n]), queue(new int[n]),
        prog(new edge *[n]) {}

  ~dinic() {
    delete[] g;
    delete[] level;
    delete[] queue;
    delete[] prog;
  }

  flow_type maximum_flow(int source_, int sink_) {
    source = source_;
    sink = sink_;
    flow_type res = 0;
    while (levelize()) {
      std::copy(g, g + n, prog);
      res += augment(source, std::numeric_limits<flow_type>::max());
    }
    return res;
  }

  edge *add_edge1(int u, int v, flow_type c, flow_type f) {
    return g[u] = new edge{u, v, c, f, g[u], nullptr};
  }

  std::pair<edge *, edge *> add_edge(int u, int v, flow_type c) {
    if (u == v || c == 0)
      return {nullptr, nullptr};
    auto uv = add_edge1(u, v, c, 0);
    auto vu = add_edge1(v, u, c, c);
    uv->rev = vu;
    vu->rev = uv;
    return {uv, vu};
  }

  bool levelize() {
    int fst = 0, lst = 0;
    queue[lst++] = source;
    std::fill(level, level + n, -1);
    level[source] = 0;
    while (fst != lst) {
      int v = queue[fst++];
      if (v == sink)
        break;
      for (auto e = g[v]; e != nullptr; e = e->next) {
        if (level[e->dst] == -1 && e->residue() != 0) {
          level[e->dst] = level[v] + 1;
          queue[lst++] = e->dst;
        }
      }
    }
    return level[sink] != -1;
  }

  flow_type augment(int v, flow_type lim) {
    flow_type res = 0;
    if (v == sink)
      return lim;
    for (auto &e = prog[v]; e; e = e->next) {
      if (lim == 0)
        break;
      if (level[v] < level[e->dst] && e->residue() != 0) {
        flow_type aug = augment(e->dst, std::min(lim, e->residue()));
        if (aug == 0)
          continue;
        e->flow += aug;
        e->rev->flow -= aug;
        res += aug;
        lim -= aug;
      }
    }
    return res;
  }
};

using namespace std;

// int main() {
//     int N, M;
//     cin >> N >> M;
//     dinic g(N);
//     while (M--) {
//         int a, b, c;
//         cin >> a >> b >> c;
//         g.add_edge(a, b, c);
//     }
//     cout << g.maximum_flow(0, N - 1) << endl;
// }
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define FOR(i, a, b) for (int i = (a); i < int(b); ++i)
#define RFOR(i, a, b) for (int i = (b)-1; i >= int(a); --i)
#define rep(i, n) FOR(i, 0, n)
#define rep1(i, n) FOR(i, 1, int(n) + 1)
#define rrep(i, n) RFOR(i, 0, n)
#define rrep1(i, n) RFOR(i, 1, int(n) + 1)
#define all(c) begin(c), end(c)
const int MOD = 1000000007;

const int INF = 1e6;

signed main() {
  int h, w;
  while (cin >> h >> w && h) {
    vector<string> g(h);

    rep(i, h) { cin >> g[i]; }
    dinic dn(h * w * 2);
    rep(i, h) {
      rep(j1, w) rep(j2, w) if (j1 != j2) {
        if (g[i][j1] != '.' && g[i][j2] != '.') {
          int u = i * w + j1;
          int v = i * w + j2 + h * w;
          dn.add_edge(u, v, INF);
        }
      }
    }
    rep(j, w) {
      rep(i1, h) rep(i2, h) if (i1 != i2) {
        if (g[i1][j] != '.' && g[i2][j] != '.') {
          int u = i1 * w + j;
          int v = i2 * w + j + h * w;
          dn.add_edge(u, v, INF);
        }
      }
    }

    rep(i, h) rep(j, w) {
      if (g[i][j] != '.') {
        int cost;
        if (g[i][j] == 'S' || g[i][j] == 'T') {
          cost = INF;
        } else {
          cost = 1;
        }
        int u = i * w + j;
        int v = i * w + j + h * w;
        dn.add_edge(v, u, cost);
      }
    }

    int si = -1, sj = -1, ti = -1, tj = -1;
    rep(i, h) rep(j, w) {
      if (g[i][j] == 'S')
        si = i, sj = j;
      if (g[i][j] == 'T')
        ti = i, tj = j;
    }
    // dump(si*w + sj, ti*w + tj + h*w);
    if (si == ti || sj == tj) {
      cout << -1;
    } else {
      cout << dn.maximum_flow(si * w + sj, ti * w + tj + h * w);
    }
    cout << endl;
    // dn.show();
  }
}