Problem p03718 (C++)

Buggy submission (status: Runtime Error):

#include <algorithm>
#include <bitset>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <vector>
using namespace std;

#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define RFOR(i, b, a) for (int i = (b)-1; i >= (a); i--)
#define ITER(it, a)                                                            \
  for (__typeof(a.begin()) it = a.begin(); it != a.end(); it++)
#define FILL(a, value) memset(a, value, sizeof(a))

#define SZ(a) (int)a.size()
#define ALL(a) a.begin(), a.end()
#define PB push_back
#define MP make_pair

typedef long long LL;
typedef vector<int> VI;
typedef pair<int, int> PII;

const double PI = acos(-1.0);
const int INF = 1000 * 1000 * 1000 + 7;
const int MOD = 1000 * 1000 * 1000 + 7;
const LL LINF = INF * (LL)INF;
const int MAX = 111;

const int MAXN = 111 * 111;

string ss[MAX];
int m[MAX][MAX];
int M[MAX][MAX];

struct edge {
  int a, b, cap, flow;
};

int n, s, t, d[MAXN], ptr[MAXN], q[MAXN];
vector<edge> e;
vector<int> g[MAXN];

void add_edge(int a, int b, int cap) {
  edge e1 = {a, b, cap, 0};
  edge e2 = {b, a, 0, 0};
  g[a].push_back((int)e.size());
  e.push_back(e1);
  g[b].push_back((int)e.size());
  e.push_back(e2);
}

bool bfs() {
  int qh = 0, qt = 0;
  q[qt++] = s;
  memset(d, -1, n * sizeof d[0]);
  d[s] = 0;
  while (qh < qt && d[t] == -1) {
    int v = q[qh++];
    for (size_t i = 0; i < g[v].size(); ++i) {
      int id = g[v][i], to = e[id].b;
      if (d[to] == -1 && e[id].flow < e[id].cap) {
        q[qt++] = to;
        d[to] = d[v] + 1;
      }
    }
  }
  return d[t] != -1;
}

int dfs(int v, int flow) {
  if (!flow)
    return 0;
  if (v == t)
    return flow;
  for (; ptr[v] < (int)g[v].size(); ++ptr[v]) {
    int id = g[v][ptr[v]], to = e[id].b;
    if (d[to] != d[v] + 1)
      continue;
    int pushed = dfs(to, min(flow, e[id].cap - e[id].flow));
    if (pushed) {
      e[id].flow += pushed;
      e[id ^ 1].flow -= pushed;
      return pushed;
    }
  }
  return 0;
}

int dinic() {
  int flow = 0;
  for (;;) {
    if (!bfs())
      break;
    memset(ptr, 0, n * sizeof ptr[0]);
    while (int pushed = dfs(s, INF))
      flow += pushed;
  }
  return flow;
}

int main() {
  int a, b;
  cin >> a >> b;
  FOR(i, 0, a)
  cin >> ss[i];

  int idx = 0;
  PII S, T;
  FOR(i, 0, a)
  FOR(j, 0, b) {
    if (ss[i][j] == '.')
      continue;
    m[i][j] = idx++;
    if (ss[i][j] == 'S') {
      M[i][j] = m[i][j];
      S = MP(i, j);
      continue;
    }
    if (ss[i][j] == 'T') {
      T = MP(i, j);
      M[i][j] = m[i][j];
      continue;
    }
    M[i][j] = idx++;
  }

  if (S.first == T.first || S.second == T.second) {
    cout << -1 << endl;
    return 0;
  }

  n = idx;
  s = m[S.first][S.second];
  t = m[T.first][T.second];

  FOR(i, 0, a)
  FOR(j, 0, b) {
    if (ss[i][j] == '.')
      continue;
    FOR(k, 0, a) {
      if (ss[k][j] == '.')
        continue;
      if (k == i)
        continue;
      add_edge(m[i][j], M[k][j], 2);
    }
    FOR(k, 0, b) {
      if (ss[i][k] == '.')
        continue;
      if (k == j)
        continue;
      add_edge(m[i][j], M[i][k], 2);
    }
  }

  FOR(i, 0, a)
  FOR(j, 0, b)
  if (m[i][j] != M[i][j])
    add_edge(M[i][j], m[i][j], 1);

  cout << dinic();

  return 0;
}


Fixed submission:

#include <algorithm>
#include <bitset>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <vector>
using namespace std;

#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define RFOR(i, b, a) for (int i = (b)-1; i >= (a); i--)
#define ITER(it, a)                                                            \
  for (__typeof(a.begin()) it = a.begin(); it != a.end(); it++)
#define FILL(a, value) memset(a, value, sizeof(a))

#define SZ(a) (int)a.size()
#define ALL(a) a.begin(), a.end()
#define PB push_back
#define MP make_pair

typedef long long LL;
typedef vector<int> VI;
typedef pair<int, int> PII;

const double PI = acos(-1.0);
const int INF = 1000 * 1000 * 1000 + 7;
const int MOD = 1000 * 1000 * 1000 + 7;
const LL LINF = INF * (LL)INF;
const int MAX = 111;

const int MAXN = 111 * 111 * 2;

string ss[MAX];
int m[MAX][MAX];
int M[MAX][MAX];

struct edge {
  int a, b, cap, flow;
};

int n, s, t, d[MAXN], ptr[MAXN], q[MAXN];
vector<edge> e;
vector<int> g[MAXN];

void add_edge(int a, int b, int cap) {
  edge e1 = {a, b, cap, 0};
  edge e2 = {b, a, 0, 0};
  g[a].push_back((int)e.size());
  e.push_back(e1);
  g[b].push_back((int)e.size());
  e.push_back(e2);
}

bool bfs() {
  int qh = 0, qt = 0;
  q[qt++] = s;
  memset(d, -1, n * sizeof d[0]);
  d[s] = 0;
  while (qh < qt && d[t] == -1) {
    int v = q[qh++];
    for (size_t i = 0; i < g[v].size(); ++i) {
      int id = g[v][i], to = e[id].b;
      if (d[to] == -1 && e[id].flow < e[id].cap) {
        q[qt++] = to;
        d[to] = d[v] + 1;
      }
    }
  }
  return d[t] != -1;
}

int dfs(int v, int flow) {
  if (!flow)
    return 0;
  if (v == t)
    return flow;
  for (; ptr[v] < (int)g[v].size(); ++ptr[v]) {
    int id = g[v][ptr[v]], to = e[id].b;
    if (d[to] != d[v] + 1)
      continue;
    int pushed = dfs(to, min(flow, e[id].cap - e[id].flow));
    if (pushed) {
      e[id].flow += pushed;
      e[id ^ 1].flow -= pushed;
      return pushed;
    }
  }
  return 0;
}

int dinic() {
  int flow = 0;
  for (;;) {
    if (!bfs())
      break;
    memset(ptr, 0, n * sizeof ptr[0]);
    while (int pushed = dfs(s, INF))
      flow += pushed;
  }
  return flow;
}

int main() {
  int a, b;
  cin >> a >> b;
  FOR(i, 0, a)
  cin >> ss[i];

  int idx = 0;
  PII S, T;
  FOR(i, 0, a)
  FOR(j, 0, b) {
    if (ss[i][j] == '.')
      continue;
    m[i][j] = idx++;
    if (ss[i][j] == 'S') {
      M[i][j] = m[i][j];
      S = MP(i, j);
      continue;
    }
    if (ss[i][j] == 'T') {
      T = MP(i, j);
      M[i][j] = m[i][j];
      continue;
    }
    M[i][j] = idx++;
  }

  if (S.first == T.first || S.second == T.second) {
    cout << -1 << endl;
    return 0;
  }

  n = idx;
  s = m[S.first][S.second];
  t = m[T.first][T.second];

  FOR(i, 0, a)
  FOR(j, 0, b) {
    if (ss[i][j] == '.')
      continue;
    FOR(k, 0, a) {
      if (ss[k][j] == '.')
        continue;
      if (k == i)
        continue;
      add_edge(m[i][j], M[k][j], 2);
    }
    FOR(k, 0, b) {
      if (ss[i][k] == '.')
        continue;
      if (k == j)
        continue;
      add_edge(m[i][j], M[i][k], 2);
    }
  }

  FOR(i, 0, a)
  FOR(j, 0, b)
  if (m[i][j] != M[i][j])
    add_edge(M[i][j], m[i][j], 1);

  cout << dinic();

  return 0;
}