Problem p03718 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <utility>
using std::min;
typedef long long int64;
static const int INF = 0x3fffffff;
static const int MAXN = 103;

namespace nwf {

static const int MAXN = 20004;
static const int MAXM = 3e6 + 3;

int n, m, source, sink;
int head[MAXN], dest[MAXM], cap[MAXM], next[MAXM];

inline void init(int _n) {
  n = _n, m = 0;
  for (int i = 0; i < n; ++i)
    head[i] = -1;
}
inline void add_edge(int u, int v, int c) {
  dest[m] = v;
  cap[m] = c;
  next[m] = head[u];
  head[u] = m++;
  dest[m] = u;
  cap[m] = 0;
  next[m] = head[v];
  head[v] = m++;
}

int d[MAXN], cur[MAXN];
inline bool level_graph() {
  static int q[MAXN], qhead, qtail;
  memset(d, -1, sizeof d);
  d[source] = 0, q[0] = source;
  qhead = 0, qtail = 1;
  while (qhead < qtail) {
    int u = q[qhead++];
    for (int w = head[u]; w != -1; w = next[w])
      if (cap[w] > 0 && d[dest[w]] == -1) {
        d[dest[w]] = d[u] + 1;
        q[qtail++] = dest[w];
      }
  }
  return (d[sink] > 0);
}

int augment(int u, int cur_cap = INF) {
  if (u == sink)
    return cur_cap;
  int new_cap;
  for (int &w = cur[u]; w != -1; w = next[w])
    if (cap[w] > 0 && d[dest[w]] == d[u] + 1 &&
        (new_cap = augment(dest[w], min(cur_cap, cap[w]))) > 0) {
      cap[w] -= new_cap;
      cap[w ^ 1] += new_cap;
      return new_cap;
    }
  return 0;
}

inline int plunge(int s, int t) {
  source = s, sink = t;
  int ans = 0, aug;
  while (level_graph()) {
    for (int i = 0; i < n; ++i)
      cur[i] = head[i];
    while ((aug = augment(source)) > 0)
      ans += aug;
  }
  return ans;
}

} // namespace nwf

int h, w;
char s[MAXN][MAXN];

inline bool is_lotus(char c) { return c == 'S' || c == 'T' || c == 'o'; }

int main() {
  scanf("%d%d", &h, &w);
  getchar();
  for (int i = 0; i < h; ++i)
    for (int j = 0; j <= w; ++j)
      s[i][j] = getchar();

  nwf::init(h * w * 2);
  for (int i = 0; i < h; ++i)
    for (int j = 0; j < w; ++j)
      if (is_lotus(s[i][j])) {
        nwf::add_edge((i * w + j) * 2, (i * w + j) * 2 + 1, 1);
        for (int ii = i - 1; ii >= 0; --ii)
          if (is_lotus(s[ii][j])) {
            nwf::add_edge((i * w + j) * 2 + 1, (ii * w + j) * 2, INF);
          }
        for (int ii = i + 1; ii < h; ++ii)
          if (is_lotus(s[ii][j])) {
            nwf::add_edge((i * w + j) * 2 + 1, (ii * w + j) * 2, INF);
          }
        for (int jj = j - 1; jj >= 0; --jj)
          if (is_lotus(s[i][jj])) {
            nwf::add_edge((i * w + j) * 2 + 1, (i * w + jj) * 2, INF);
          }
        for (int jj = j + 1; jj < w; ++jj)
          if (is_lotus(s[i][jj])) {
            nwf::add_edge((i * w + j) * 2 + 1, (i * w + jj) * 2, INF);
          }
      }

  int s_id = -1, t_id = -1;
  for (int i = 0; i < h; ++i)
    for (int j = 0; j < w; ++j)
      if (s[i][j] == 'S')
        s_id = (i * w + j) * 2 + 1;
      else if (s[i][j] == 'T')
        t_id = (i * w + j) * 2;
  int ans = nwf::plunge(s_id, t_id);
  printf("%d\n", ans > INF / 2 ? -1 : ans);

  return 0;
}


Fixed submission:
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <utility>
using std::min;
typedef long long int64;
static const int INF = 0x3fffffff;
static const int MAXN = 103;

namespace nwf {

static const int MAXN = 20004;
static const int MAXM = 1e7 + 3;

int n, m, source, sink;
int head[MAXN], dest[MAXM], cap[MAXM], next[MAXM];

inline void init(int _n) {
  n = _n, m = 0;
  for (int i = 0; i < n; ++i)
    head[i] = -1;
}
inline void add_edge(int u, int v, int c) {
  dest[m] = v;
  cap[m] = c;
  next[m] = head[u];
  head[u] = m++;
  dest[m] = u;
  cap[m] = 0;
  next[m] = head[v];
  head[v] = m++;
}

int d[MAXN], cur[MAXN];
inline bool level_graph() {
  static int q[MAXN], qhead, qtail;
  memset(d, -1, sizeof d);
  d[source] = 0, q[0] = source;
  qhead = 0, qtail = 1;
  while (qhead < qtail) {
    int u = q[qhead++];
    for (int w = head[u]; w != -1; w = next[w])
      if (cap[w] > 0 && d[dest[w]] == -1) {
        d[dest[w]] = d[u] + 1;
        q[qtail++] = dest[w];
      }
  }
  return (d[sink] > 0);
}

int augment(int u, int cur_cap = INF) {
  if (u == sink)
    return cur_cap;
  int new_cap;
  for (int &w = cur[u]; w != -1; w = next[w])
    if (cap[w] > 0 && d[dest[w]] == d[u] + 1 &&
        (new_cap = augment(dest[w], min(cur_cap, cap[w]))) > 0) {
      cap[w] -= new_cap;
      cap[w ^ 1] += new_cap;
      return new_cap;
    }
  return 0;
}

inline int plunge(int s, int t) {
  source = s, sink = t;
  int ans = 0, aug;
  while (level_graph()) {
    for (int i = 0; i < n; ++i)
      cur[i] = head[i];
    while ((aug = augment(source)) > 0)
      ans += aug;
  }
  return ans;
}

} // namespace nwf

int h, w;
char s[MAXN][MAXN];

inline bool is_lotus(char c) { return c == 'S' || c == 'T' || c == 'o'; }

int main() {
  scanf("%d%d", &h, &w);
  getchar();
  for (int i = 0; i < h; ++i)
    for (int j = 0; j <= w; ++j)
      s[i][j] = getchar();

  nwf::init(h * w * 2);
  for (int i = 0; i < h; ++i)
    for (int j = 0; j < w; ++j)
      if (is_lotus(s[i][j])) {
        nwf::add_edge((i * w + j) * 2, (i * w + j) * 2 + 1, 1);
        for (int ii = i - 1; ii >= 0; --ii)
          if (is_lotus(s[ii][j])) {
            nwf::add_edge((i * w + j) * 2 + 1, (ii * w + j) * 2, INF);
          }
        for (int ii = i + 1; ii < h; ++ii)
          if (is_lotus(s[ii][j])) {
            nwf::add_edge((i * w + j) * 2 + 1, (ii * w + j) * 2, INF);
          }
        for (int jj = j - 1; jj >= 0; --jj)
          if (is_lotus(s[i][jj])) {
            nwf::add_edge((i * w + j) * 2 + 1, (i * w + jj) * 2, INF);
          }
        for (int jj = j + 1; jj < w; ++jj)
          if (is_lotus(s[i][jj])) {
            nwf::add_edge((i * w + j) * 2 + 1, (i * w + jj) * 2, INF);
          }
      }

  int s_id = -1, t_id = -1;
  for (int i = 0; i < h; ++i)
    for (int j = 0; j < w; ++j)
      if (s[i][j] == 'S')
        s_id = (i * w + j) * 2 + 1;
      else if (s[i][j] == 'T')
        t_id = (i * w + j) * 2;
  int ans = nwf::plunge(s_id, t_id);
  printf("%d\n", ans > INF / 2 ? -1 : ans);

  return 0;
}