Problem p02561 (C++) — buggy submission, verdict: Runtime Error

#include <bits/stdc++.h>
using namespace std;

// BEGIN CUT HERE
template <typename T, bool directed> // directedは有向のこと
struct Fordfulkerson {
  struct edge {
    int to, cap, rev;
    edge() {}
    edge(int to, int cap, int rev) : to(to), cap(cap), rev(rev) {}
  };

  vector<vector<edge>> G;
  vector<int> used;

  Fordfulkerson() {}
  Fordfulkerson(int n) : G(n), used(n) {} // n個の頂点

  void add_edge(int from, int to, T cap) {
    G[from].emplace_back(to, cap, G[to].size()); // edgeのrevには逆辺の番号が入る
    G[to].emplace_back(from, directed ? 0 : cap,
                       G[from].size() - 1); // 有向グラフならcapは0
  }

  T dfs(
      int v, int t,
      T f) { // v->tにfの流量を道が見つかり次第通していく感じ　通った量が返り値
    if (v == t)
      return f;     // ゴール
    used[v] = true; // 通った確認
    for (int i = 0; i < (int)G[v].size(); i++) {
      edge &e = G[v][i];
      if (!used[e.to] &&
          e.cap > 0) { // まだ通ってなくてcap的にいける場所があるなら
        T d = dfs(e.to, t,
                  min(f, e.cap)); // そこからtまで通せるだけ通そうとして見る
        if (d > 0) {               // dだけ通った
          e.cap -= d;              // 流量を減らす
          G[e.to][e.rev].cap += d; // 逆辺の流量を増やす
          return d;                // d通せた
        }
      }
    }
    return 0;
  }

  int flow(int s, int t, T lim) {
    T fl = 0;
    while (1) {
      fill(used.begin(), used.end(), 0); // usedの初期化
      T f = dfs(s, t, lim); // sからtまで逆辺を考慮しつつ通す
      if (f == 0)
        break;  // 全く通らないなら終了
      fl += f;  // 通ってるなら流量を増やす
      lim -= f; // 初期流量を減らす
    }
    return fl;
  }

  int flow(int s, int t) { // 全力で流す
    return flow(s, t, numeric_limits<T>::max() / 2);
  }
};
// END CUT HERE

signed main() {
  int n, m;
  cin >> n >> m;
  vector<string> s(n);
  for (int i = 0; i < n; i++)
    cin >> s[i];
  Fordfulkerson<int, 1> fl(n * m + 2);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if ((i + j) & 1) {
        fl.add_edge(n * m, i * m + j, 1);
        if (i + 1 < n && s[i][j] == '.' && s[i + 1][j] == '.')
          fl.add_edge(i * m + j, (i + 1) * m + j, 1);
        if (i - 1 >= 0 && s[i][j] == '.' && s[i - 1][j] == '.')
          fl.add_edge(i * m + j, (i - 1) * m + j, 1);
        if (j + 1 < m && s[i][j] == '.' && s[i][j + 1] == '.')
          fl.add_edge(i * m + j, i * m + j + 1, 1);
        if (j - 1 >= 0 && s[i][j] == '.' && s[i][j - 1] == '.')
          fl.add_edge(i * m + j, i * m + j - 1, 1);
      } else
        fl.add_edge(i * m + j, n * m + 1, 1);
    }
  }
  cout << fl.flow(n * m, n * m + 1) << endl;
  for (int i = 0; i < n * m; i++) {
    for (auto e : fl.G[i]) {
      int y1 = i / m, x1 = i % m, y2 = e.to / m, x2 = e.to % m;
      if (!((y1 + x1) & 1) || y2 >= n || e.cap)
        continue;
      if (i > e.to)
        swap(y1, y2), swap(x1, x2);
      if (y1 == y2)
        s[y1][x1] = '>', s[y2][x2] = '<';
      else
        s[y1][x1] = 'v', s[y2][x2] = '^';
    }
  }
  for (int i = 0; i < n; i++)
    cout << s[i] << endl;
}


Error: 0

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

// BEGIN CUT HERE
template <typename T, bool directed> // directedは有向のこと
struct Fordfulkerson {
  struct edge {
    int to, cap, rev;
    edge() {}
    edge(int to, int cap, int rev) : to(to), cap(cap), rev(rev) {}
  };

  vector<vector<edge>> G;
  vector<int> used;

  Fordfulkerson() {}
  Fordfulkerson(int n) : G(n), used(n) {} // n個の頂点

  void add_edge(int from, int to, T cap) {
    G[from].emplace_back(to, cap, G[to].size()); // edgeのrevには逆辺の番号が入る
    G[to].emplace_back(from, directed ? 0 : cap,
                       G[from].size() - 1); // 有向グラフならcapは0
  }

  T dfs(
      int v, int t,
      T f) { // v->tにfの流量を道が見つかり次第通していく感じ　通った量が返り値
    if (v == t)
      return f;     // ゴール
    used[v] = true; // 通った確認
    for (int i = 0; i < (int)G[v].size(); i++) {
      edge &e = G[v][i];
      if (!used[e.to] &&
          e.cap > 0) { // まだ通ってなくてcap的にいける場所があるなら
        T d = dfs(e.to, t,
                  min(f, e.cap)); // そこからtまで通せるだけ通そうとして見る
        if (d > 0) {               // dだけ通った
          e.cap -= d;              // 流量を減らす
          G[e.to][e.rev].cap += d; // 逆辺の流量を増やす
          return d;                // d通せた
        }
      }
    }
    return 0;
  }

  int flow(int s, int t, T lim) {
    T fl = 0;
    while (1) {
      fill(used.begin(), used.end(), 0); // usedの初期化
      T f = dfs(s, t, lim); // sからtまで逆辺を考慮しつつ通す
      if (f == 0)
        break;  // 全く通らないなら終了
      fl += f;  // 通ってるなら流量を増やす
      lim -= f; // 初期流量を減らす
    }
    return fl;
  }

  int flow(int s, int t) { // 全力で流す
    return flow(s, t, numeric_limits<T>::max() / 2);
  }
};
// END CUT HERE

signed main() {
  int n, m;
  cin >> n >> m;
  vector<string> s(n);
  for (int i = 0; i < n; i++)
    cin >> s[i];
  Fordfulkerson<int, 0> fl(n * m + 2);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if ((i + j) & 1)
        fl.add_edge(n * m, i * m + j, 1);
      else
        fl.add_edge(i * m + j, n * m + 1, 1);
      if (i + 1 < n && s[i][j] == '.' && s[i + 1][j] == '.')
        fl.add_edge(i * m + j, (i + 1) * m + j, 1);
      if (j + 1 < m && s[i][j] == '.' && s[i][j + 1] == '.')
        fl.add_edge(i * m + j, i * m + j + 1, 1);
    }
  }
  auto insert = [&](int i, int j, char c) {
    assert(0 <= i && i < n && 0 <= j && j < m && s[i][j] == '.');
    s[i][j] = c;
  };
  cout << fl.flow(n * m, n * m + 1) << endl;
  for (int i = 0; i < n * m; i++) {
    for (auto e : fl.G[i]) {
      int y1 = i / m, x1 = i % m, y2 = e.to / m, x2 = e.to % m;
      if (!((y1 + x1) & 1) || y2 >= n || e.cap)
        continue;
      if (i > e.to)
        swap(y1, y2), swap(x1, x2);
      if (y1 == y2)
        insert(y1, x1, '>'), insert(y2, x2, '<');
      else
        insert(y1, x1, 'v'), insert(y2, x2, '^');
    }
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (s[i][j] == '>')
        assert(j + 1 < m && s[i][j + 1] == '<');
      if (s[i][j] == '<')
        assert(j - 1 >= 0 && s[i][j - 1] == '>');
      if (s[i][j] == '^')
        assert(i - 1 >= 0 && s[i - 1][j] == 'v');
      if (s[i][j] == 'v')
        assert(i + 1 < n && s[i + 1][j] == '^');
    }
  }
  for (int i = 0; i < n; i++)
    cout << s[i] << endl;
}