Problem p03718 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
#define REP(i, a, b) for (int i = (a); i < (b); i++)
#define RREP(i, a, b) for (int i = (a); i >= (b); i--)
#define pq priority_queue
#define P pair<int, int>
#define P2 pair<int, P>
#define P3 pair<int, P2>
typedef long long ll;
typedef long double ld;
using namespace std;
const int INF = 1e9, MOD = 1e9 + 7,
          around[] = {0, 1, 1, -1, -1, 0, -1, 1, 0, 0};
const int vx[] = {1, 0, -1, 0}, vy[] = {0, 1, 0, -1};
const ld PI = abs(acos(-1));
const int sqrtN = 512;
const int logN = 32;
const ll LINF = 1e18;

int h, w;

int func(int i, int j, bool f) { return i + j * w + f * h * w; }

template <typename T> struct Dinic {
  struct edge {
    int to;
    T cap;
    int rev;
  };

  const T INF;
  vector<vector<edge>> g;
  vector<T> min_cost;
  vector<int> itr;

  Dinic(int n) : INF(numeric_limits<T>::max()) { g.resize(n); }

  void add_edge(int from, int to, T cap) {
    g[from].push_back(edge{to, cap, (int)g[to].size()});
    g[to].push_back(edge{from, 0, (int)g[from].size() - 1});
  }

  bool bfs(int s, int t) {
    min_cost.assign(g.size(), -1);
    queue<int> qu;
    qu.push(s);
    min_cost[s] = 0;

    while (!qu.empty()) {
      auto p = qu.front();
      qu.pop();

      for (auto e : g[p]) {
        if (e.cap <= 0 or min_cost[e.to] != -1)
          continue;
        min_cost[e.to] = min_cost[p] + 1;
        qu.push(e.to);
      }
    }

    return min_cost[t] != -1;
  }

  T dfs(int idx, const int t, T flow) {
    if (idx == t)
      return flow;
    for (int &i = itr[idx]; i < g[idx].size(); i++) {
      edge &e = g[idx][i];

      if (e.cap <= 0 or min_cost[idx] >= min_cost[e.to])
        continue;
      T d = dfs(e.to, t, min(flow, e.cap));
      if (d > 0) {
        e.cap -= d;
        g[e.to][e.rev].cap += d;
        return d;
      }
    }

    return 0;
  }

  T max_flow(int s, int t) {
    T flow = 0;
    while (bfs(s, t)) {
      itr.assign(g.size(), 0);
      T f = 0;
      while ((f = dfs(s, t, INF)) > 0)
        flow += f;
    }

    return flow;
  }
};

int main() {
  cin >> h >> w;
  string s[110];
  for (int i = 0; i < h; i++)
    cin >> s[i];
  Dinic<int> dinic(h * w * 2);

  int st, t;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      if (s[i][j] == 'S')
        st = func(i, j, false);
      if (s[i][j] == 'T')
        t = func(i, j, true);
      if (s[i][j] == '.')
        continue;

      dinic.add_edge(func(i, j, true), func(i, j, false), 1);
      for (int k = 0; k < h; k++) {
        if (i == k)
          continue;
        if (s[k][j] == '.')
          continue;
        dinic.add_edge(func(i, j, false), func(k, j, true), INF);
      }

      for (int k = 0; k < w; k++) {
        if (j == k)
          continue;
        if (s[i][k] == '.')
          continue;
        dinic.add_edge(func(i, j, false), func(i, k, true), INF);
      }
    }
  }

  ll pos = dinic.max_flow(st, t);
  cout << (pos >= INF ? -1 : pos) << endl;
  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
#define REP(i, a, b) for (int i = (a); i < (b); i++)
#define RREP(i, a, b) for (int i = (a); i >= (b); i--)
#define pq priority_queue
#define P pair<int, int>
#define P2 pair<int, P>
#define P3 pair<int, P2>
typedef long long ll;
typedef long double ld;
using namespace std;
const int INF = 1e9, MOD = 1e9 + 7,
          around[] = {0, 1, 1, -1, -1, 0, -1, 1, 0, 0};
const int vx[] = {1, 0, -1, 0}, vy[] = {0, 1, 0, -1};
const ld PI = abs(acos(-1));
const int sqrtN = 512;
const int logN = 32;
const ll LINF = 1e18;

int h, w;

int func(int i, int j, bool f) { return i * w + j + f * h * w; }

template <typename T> struct Dinic {
  struct edge {
    int to;
    T cap;
    int rev;
  };

  const T INF;
  vector<vector<edge>> g;
  vector<T> min_cost;
  vector<int> itr;

  Dinic(int n) : INF(numeric_limits<T>::max()) { g.resize(n); }

  void add_edge(int from, int to, T cap) {
    g[from].push_back(edge{to, cap, (int)g[to].size()});
    g[to].push_back(edge{from, 0, (int)g[from].size() - 1});
  }

  bool bfs(int s, int t) {
    min_cost.assign(g.size(), -1);
    queue<int> qu;
    qu.push(s);
    min_cost[s] = 0;

    while (!qu.empty()) {
      auto p = qu.front();
      qu.pop();

      for (auto e : g[p]) {
        if (e.cap <= 0 or min_cost[e.to] != -1)
          continue;
        min_cost[e.to] = min_cost[p] + 1;
        qu.push(e.to);
      }
    }

    return min_cost[t] != -1;
  }

  T dfs(int idx, const int t, T flow) {
    if (idx == t)
      return flow;
    for (int &i = itr[idx]; i < g[idx].size(); i++) {
      edge &e = g[idx][i];

      if (e.cap <= 0 or min_cost[idx] >= min_cost[e.to])
        continue;
      T d = dfs(e.to, t, min(flow, e.cap));
      if (d > 0) {
        e.cap -= d;
        g[e.to][e.rev].cap += d;
        return d;
      }
    }

    return 0;
  }

  T max_flow(int s, int t) {
    T flow = 0;
    while (bfs(s, t)) {
      itr.assign(g.size(), 0);
      T f = 0;
      while ((f = dfs(s, t, INF)) > 0)
        flow += f;
    }

    return flow;
  }
};

int main() {
  cin >> h >> w;
  string s[110];
  for (int i = 0; i < h; i++)
    cin >> s[i];
  Dinic<int> dinic(h * w * 2);

  int st, t;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      if (s[i][j] == 'S')
        st = func(i, j, false);
      if (s[i][j] == 'T')
        t = func(i, j, true);
      if (s[i][j] == '.')
        continue;

      dinic.add_edge(func(i, j, true), func(i, j, false), 1);
      for (int k = 0; k < h; k++) {
        if (i == k)
          continue;
        if (s[k][j] == '.')
          continue;
        dinic.add_edge(func(i, j, false), func(k, j, true), INF);
      }

      for (int k = 0; k < w; k++) {
        if (j == k)
          continue;
        if (s[i][k] == '.')
          continue;
        dinic.add_edge(func(i, j, false), func(i, k, true), INF);
      }
    }
  }

  ll pos = dinic.max_flow(st, t);
  cout << (pos >= INF ? -1 : pos) << endl;
  return 0;
}