Problem p03718 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define clr(a, h) memset(a, (h), sizeof(a))
#define mem(a, h) memset(a, (h), sizeof(a))
#define fi first
#define se second
#define por(a, b) (((a % MOD) * (b % MOD)) % MOD)
#define forg(i, b, e, c) for (ll i = (ll)b; i < (ll)e; i += c)
#define forr(i, b, e) for (ll i = b; i < e; i++)

using namespace std;
// using namespace __gnu_pbds;
typedef double lldb;
typedef pair<ll, ll> ii;
typedef pair<ii, ll> iii;
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef vector<ii> vii;
typedef vector<ll> vll;
// typedef
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
// ordered_set;
const ll INF = 1e9;
const double PI = acos(-1);
#define offset
const ll MOD = 1e9 + 7;
#define initseg ll new_nodo = (nodo * 2), mid = (iz + der) / 2;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int tam = 10010;

int S, T;
int n;
int dist[tam], q[tam], work[tam];

struct Edge {
  int to, rev;
  int f, cap;
};

vector<Edge> G[tam];

void addEdge(int s, int t, int cap) {
  Edge a = {t, (int)G[t].size(), 0, cap};
  Edge b = {s, (int)G[s].size(), 0, 0};
  G[s].pb(a);
  G[t].pb(b);
}

bool dinic_BFS() {
  fill(dist, dist + n + 2, -1);
  dist[S] = 0;
  int qt = 0;
  q[qt++] = S;
  for (int qh = 0; qh < qt; qh++) {
    int u = q[qh];
    for (int j = 0; j < G[u].size(); j++) {
      Edge &e = G[u][j];
      int v = e.to;
      if (dist[v] < 0 && e.f < e.cap) {
        dist[v] = dist[u] + 1;
        q[qt++] = v;
      }
    }
  }
  return dist[T] >= 0;
}

int dinic_DFS(int u, int f) {
  if (u == T || f == 0)
    return f;
  for (int &i = work[u]; i < G[u].size(); i++) {
    Edge &e = G[u][i];
    if (e.cap <= e.f)
      continue;
    int v = e.to;
    if (dist[v] == dist[u] + 1) {
      int df = dinic_DFS(v, min(f, e.cap - e.f));
      if (df > 0) {
        e.f += df;
        G[v][e.rev].f -= df;
        return df;
      }
    }
  }
  return 0;
}

int maxFlow() {
  int flow = 0;
  while (dinic_BFS()) {
    fill(work, work + n + 2, 0);
    while (true) {
      int df = dinic_DFS(S, INF);
      if (df == 0)
        break;
      flow += df;
    }
  }
  return flow;
}
int N, M;
string txt[tam];
int getnod(int y, int x) { return y * M + x; }
void go(int i, int j) {
  int inicial = getnod(i, j), final;
  addEdge(inicial * 2, inicial * 2 + 1, 1);
  forr(k, 0, M) {
    if (txt[i][k] != '.') {
      final = getnod(i, k);
      addEdge(inicial * 2 + 1, final * 2, INF);
    }
  }
  forr(k, 0, N) {
    if (txt[k][j] != ',') {
      final = getnod(k, j);
      addEdge(inicial * 2 + 1, final * 2, INF);
    }
  }
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  cin >> N >> M;
  n = getnod(N, M) * 2 + 1;
  int inicial, final;
  int y, x;
  forr(i, 0, N) {
    cin >> txt[i];
    forr(j, 0, M) {
      if (txt[i][j] == 'S') {
        S = getnod(i, j) * 2;
        y = i;
        x = j;
        continue;
      }
      if (txt[i][j] == 'T') {
        T = getnod(i, j) * 2;
        continue;
      }
      if (txt[i][j] == '.')
        continue;
      go(i, j);
    }
  }

  forr(k, 0, M) {
    if (txt[y][k] != '.') {
      final = getnod(y, k);

      addEdge(S, final * 2, INF);
    }
  }
  forr(k, 0, N) {
    if (txt[k][x] != ',') {
      final = getnod(k, x);
      addEdge(S, final * 2, INF);
    }
  }
  int res = maxFlow();
  if (res < INF)
    cout << res << endl;
  else
    cout << -1 << endl;
}
// PLUS ULTRA!ac

Fixed submission:
#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define clr(a, h) memset(a, (h), sizeof(a))
#define mem(a, h) memset(a, (h), sizeof(a))
#define fi first
#define se second
#define por(a, b) (((a % MOD) * (b % MOD)) % MOD)
#define forg(i, b, e, c) for (ll i = (ll)b; i < (ll)e; i += c)
#define forr(i, b, e) for (ll i = b; i < e; i++)

using namespace std;
// using namespace __gnu_pbds;
typedef double lldb;
typedef pair<ll, ll> ii;
typedef pair<ii, ll> iii;
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef vector<ii> vii;
typedef vector<ll> vll;
// typedef
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>
// ordered_set;
const ll INF = 1e9;
const double PI = acos(-1);
#define offset
const ll MOD = 1e9 + 7;
#define initseg ll new_nodo = (nodo * 2), mid = (iz + der) / 2;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int tam = 30000;

int S, T;
int n;
int dist[tam], q[tam], work[tam];

struct Edge {
  int to, rev;
  int f, cap;
};

vector<Edge> G[tam];

void addEdge(int s, int t, int cap) {
  Edge a = {t, (int)G[t].size(), 0, cap};
  Edge b = {s, (int)G[s].size(), 0, 0};
  G[s].pb(a);
  G[t].pb(b);
}

bool dinic_BFS() {
  fill(dist, dist + n + 2, -1);
  dist[S] = 0;
  int qt = 0;
  q[qt++] = S;
  for (int qh = 0; qh < qt; qh++) {
    int u = q[qh];
    for (int j = 0; j < G[u].size(); j++) {
      Edge &e = G[u][j];
      int v = e.to;
      if (dist[v] < 0 && e.f < e.cap) {
        dist[v] = dist[u] + 1;
        q[qt++] = v;
      }
    }
  }
  return dist[T] >= 0;
}

int dinic_DFS(int u, int f) {
  if (u == T || f == 0)
    return f;
  for (int &i = work[u]; i < G[u].size(); i++) {
    Edge &e = G[u][i];
    if (e.cap <= e.f)
      continue;
    int v = e.to;
    if (dist[v] == dist[u] + 1) {
      int df = dinic_DFS(v, min(f, e.cap - e.f));
      if (df > 0) {
        e.f += df;
        G[v][e.rev].f -= df;
        return df;
      }
    }
  }
  return 0;
}

int maxFlow() {
  int flow = 0;
  while (dinic_BFS()) {
    fill(work, work + n + 2, 0);
    while (true) {
      int df = dinic_DFS(S, INF);
      if (df == 0)
        break;
      flow += df;
    }
  }
  return flow;
}
int N, M;
string txt[tam];
int getnod(int y, int x) { return y * M + x; }
void go(int i, int j) {
  int inicial = getnod(i, j), final;
  addEdge(inicial * 2, inicial * 2 + 1, 1);
  forr(k, 0, M) {
    if (txt[i][k] != '.') {
      final = getnod(i, k);
      addEdge(inicial * 2 + 1, final * 2, INF);
    }
  }
  forr(k, 0, N) {
    if (txt[k][j] != ',') {
      final = getnod(k, j);
      addEdge(inicial * 2 + 1, final * 2, INF);
    }
  }
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  cin >> N >> M;
  n = getnod(N, M) * 2 + 1;
  int inicial, final;
  int y, x;
  forr(i, 0, N) {
    cin >> txt[i];
    forr(j, 0, M) {
      if (txt[i][j] == 'S') {
        S = getnod(i, j) * 2;
        y = i;
        x = j;
        continue;
      }
      if (txt[i][j] == 'T') {
        T = getnod(i, j) * 2;
        continue;
      }
      if (txt[i][j] == '.')
        continue;
      go(i, j);
    }
  }

  forr(k, 0, M) {
    if (txt[y][k] != '.') {
      final = getnod(y, k);

      addEdge(S, final * 2, INF);
    }
  }
  forr(k, 0, N) {
    if (txt[k][x] != ',') {
      final = getnod(k, x);
      addEdge(S, final * 2, INF);
    }
  }
  int res = maxFlow();
  if (res < INF)
    cout << res << endl;
  else
    cout << -1 << endl;
}
// PLUS ULTRA!ac