Problem p03718 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cmath>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <typeinfo>
#include <unordered_map>
#include <utility>
#include <vector>
using namespace std;

using ll = long long;
using vll = vector<ll>;
using pll = pair<ll, ll>;
using qll = queue<ll>;
using vb = vector<bool>;
using mll = map<ll, ll>;
using sll = stack<ll>;
#define REP(i, n) for (ll i(0); (i) < (n); (i)++)
#define rep(i, n) for (ll i(0); (i) < (n); (i)++)
#define ALL(a) a.begin(), a.end()
#define enld endl //* missspell check
const ll INF = 1LL << 60;
ll H, W;
vector<string> S;

struct edgeForFlow {
  ll to, cap, rev;
}; //! cap: may change; rev: pointer in G[to]

void addEdgeForFlow(vector<vector<edgeForFlow>> &G, ll from, ll to, ll cap) {
  G[from].push_back((edgeForFlow){to, cap, (ll)G[to].size()});
  G[to].push_back((edgeForFlow){from, 0, (ll)G[from].size() - 1});
}

ll dfsFordFulkson(vector<vector<edgeForFlow>> &G, vb &checked, ll v, ll t,
                  ll f) {
  //* v: current vertex, t: sink, f: DELTA of this path. (No need for source)
  if (v == t)
    return f;
  checked[v] = true;
  REP(i, G[v].size()) {
    edgeForFlow &e = G[v][i];
    if (!checked[e.to] && e.cap > 0) {
      ll d = dfsFordFulkson(G, checked, e.to, t, min(f, e.cap));
      if (d > 0) {
        e.cap -= d;
        G[e.to][e.rev].cap += d;
        return d;
      }
    }
  }
  return 0; //* if no valid outgoing edges
}

ll maxFlowFordFulkson(vector<vector<edgeForFlow>> &G, ll s, ll t) {
  vb checked(G.size());
  ll flow = 0;
  for (;;) {
    fill(ALL(checked), false);
    ll f = dfsFordFulkson(G, checked, s, t, INF);
    if (f == 0)
      return flow;
    flow += f;
  }
}

void bfsDinic(vector<vector<edgeForFlow>> &G, vll &level, ll s) {
  fill(ALL(level), -1);
  queue<ll> que;
  level[s] = 0;
  que.push(s);
  while (!que.empty()) {
    ll v = que.front();
    que.pop();
    for (ll i = 0; i < G[v].size(); i++) {
      edgeForFlow &e = G[v][i];
      if (e.cap > 0 && level[e.to] < 0) {
        level[e.to] = level[v] + 1;
        que.push(e.to);
      }
    }
  }
}

ll dfsDinic(vector<vector<edgeForFlow>> &G, vll &level, vll &iter, ll v, ll t,
            ll f) {
  //? iter: record where have been searched?
  //* v: current vertex, t: sink, f: DELTA of this path. (No need for source)
  if (v == t)
    return f;
  for (ll &i = iter[v]; i < G[v].size(); i++) {
    edgeForFlow &e = G[v][i];
    if (e.cap > 0 && level[v] < level[e.to]) {
      ll d = dfsDinic(G, level, iter, e.to, t, min(f, e.cap));
      if (d > 0) {
        e.cap -= d;
        G[e.to][e.rev].cap += d;
        return d;
      }
    }
  }
  return 0; //* if no valid outgoing edges
}

ll maxFlowDinic(vector<vector<edgeForFlow>> &G, ll s, ll t) {
  vll level(G.size()), iter(G.size());
  ll flow = 0;
  for (;;) {
    bfsDinic(G, level, s);
    if (level[t] <
        0) //* sink t is not reachable from s on current residual graph
      return flow;
    fill(ALL(iter), 0);
    ll f;
    while ((f = dfsDinic(G, level, iter, s, t, INF)) > 0) {
      flow += f;
    }
  }
}

int main() {
  cin >> H >> W;
  S.resize(H);
  REP(i, H) { cin >> S[i]; }
  vector<vector<edgeForFlow>> G(H + W + 2);
  //* G[H+W]: S, G[H+W+1]: T
  REP(i, H) {
    REP(j, H) {
      if (S[i][j] == '.')
        continue;
      if (S[i][j] == 'o') {
        addEdgeForFlow(G, i, j + H, 1);
        addEdgeForFlow(G, j + H, i, 1);
      } else if (S[i][j] == 'S') {
        addEdgeForFlow(G, H + W, i, H * W);
        addEdgeForFlow(G, H + W, j + H, H * W);
      } else { //*S[i][j] == 'T'
        addEdgeForFlow(G, i, H + W + 1, H * W);
        addEdgeForFlow(G, j + H, H + W + 1, H * W);
      }
    }
  }
  ll flow = 0;
  flow = maxFlowDinic(G, H + W, H + W + 1);
  if (flow >= H * W) {
    cout << -1 << endl;
  } else {
    cout << flow << endl;
  }
  return 0;
}


Fixed submission:
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cmath>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <typeinfo>
#include <unordered_map>
#include <utility>
#include <vector>
using namespace std;

using ll = long long;
using vll = vector<ll>;
using pll = pair<ll, ll>;
using qll = queue<ll>;
using vb = vector<bool>;
using mll = map<ll, ll>;
using sll = stack<ll>;
#define REP(i, n) for (ll i(0); (i) < (n); (i)++)
#define rep(i, n) for (ll i(0); (i) < (n); (i)++)
#define ALL(a) a.begin(), a.end()
#define enld endl //* missspell check
const ll INF = 1LL << 60;
ll H, W;
vector<string> S;

struct edgeForFlow {
  ll to, cap, rev;
}; //! cap: may change; rev: pointer in G[to]

void addEdgeForFlow(vector<vector<edgeForFlow>> &G, ll from, ll to, ll cap) {
  G[from].push_back((edgeForFlow){to, cap, (ll)G[to].size()});
  G[to].push_back((edgeForFlow){from, 0, (ll)G[from].size() - 1});
}

ll dfsFordFulkson(vector<vector<edgeForFlow>> &G, vb &checked, ll v, ll t,
                  ll f) {
  //* v: current vertex, t: sink, f: DELTA of this path. (No need for source)
  if (v == t)
    return f;
  checked[v] = true;
  REP(i, G[v].size()) {
    edgeForFlow &e = G[v][i];
    if (!checked[e.to] && e.cap > 0) {
      ll d = dfsFordFulkson(G, checked, e.to, t, min(f, e.cap));
      if (d > 0) {
        e.cap -= d;
        G[e.to][e.rev].cap += d;
        return d;
      }
    }
  }
  return 0; //* if no valid outgoing edges
}

ll maxFlowFordFulkson(vector<vector<edgeForFlow>> &G, ll s, ll t) {
  vb checked(G.size());
  ll flow = 0;
  for (;;) {
    fill(ALL(checked), false);
    ll f = dfsFordFulkson(G, checked, s, t, INF);
    if (f == 0)
      return flow;
    flow += f;
  }
}

void bfsDinic(vector<vector<edgeForFlow>> &G, vll &level, ll s) {
  fill(ALL(level), -1);
  queue<ll> que;
  level[s] = 0;
  que.push(s);
  while (!que.empty()) {
    ll v = que.front();
    que.pop();
    for (ll i = 0; i < G[v].size(); i++) {
      edgeForFlow &e = G[v][i];
      if (e.cap > 0 && level[e.to] < 0) {
        level[e.to] = level[v] + 1;
        que.push(e.to);
      }
    }
  }
}

ll dfsDinic(vector<vector<edgeForFlow>> &G, vll &level, vll &iter, ll v, ll t,
            ll f) {
  //? iter: record where have been searched?
  //* v: current vertex, t: sink, f: DELTA of this path. (No need for source)
  if (v == t)
    return f;
  for (ll &i = iter[v]; i < G[v].size(); i++) {
    edgeForFlow &e = G[v][i];
    if (e.cap > 0 && level[v] < level[e.to]) {
      ll d = dfsDinic(G, level, iter, e.to, t, min(f, e.cap));
      if (d > 0) {
        e.cap -= d;
        G[e.to][e.rev].cap += d;
        return d;
      }
    }
  }
  return 0; //* if no valid outgoing edges
}

ll maxFlowDinic(vector<vector<edgeForFlow>> &G, ll s, ll t) {
  vll level(G.size()), iter(G.size());
  ll flow = 0;
  for (;;) {
    bfsDinic(G, level, s);
    if (level[t] <
        0) //* sink t is not reachable from s on current residual graph
      return flow;
    fill(ALL(iter), 0);
    ll f;
    while ((f = dfsDinic(G, level, iter, s, t, INF)) > 0) {
      flow += f;
    }
  }
}

int main() {
  cin >> H >> W;
  S.resize(H);
  REP(i, H) { cin >> S[i]; }
  vector<vector<edgeForFlow>> G(H + W + 2);
  //* G[H+W]: S, G[H+W+1]: T
  REP(i, H) {
    REP(j, W) {
      if (S[i][j] == '.')
        continue;
      if (S[i][j] == 'o') {
        addEdgeForFlow(G, i, j + H, 1);
        addEdgeForFlow(G, j + H, i, 1);
      } else if (S[i][j] == 'S') {
        addEdgeForFlow(G, H + W, i, H * W);
        addEdgeForFlow(G, H + W, j + H, H * W);
      } else { //*S[i][j] == 'T'
        addEdgeForFlow(G, i, H + W + 1, H * W);
        addEdgeForFlow(G, j + H, H + W + 1, H * W);
      }
    }
  }
  ll flow = 0;
  flow = maxFlowDinic(G, H + W, H + W + 1);
  if (flow >= H * W) {
    cout << -1 << endl;
  } else {
    cout << flow << endl;
  }
  return 0;
}