Problem p02561 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstring>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <istream>

#include <map>
#include <math.h>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include <stdint.h>

namespace asl {
template <typename T> using vec = std::vector<T>;

template <typename T>
std::istream &operator>>(std::istream &is, std::vector<T> &vec) {
  for (auto &value : vec)
    is >> value;
  return is;
}

} // namespace asl

#include <experimental/optional>

namespace asl {

template <typename C, typename R = C> class Dinic {
public:
  typedef C flow_type;
  typedef R result_type;

  static_assert(std::is_arithmetic<flow_type>::value,
                "flow_type must be arithmetic");
  static_assert(std::is_arithmetic<result_type>::value,
                "result_type must be arithmetic");

  static const flow_type oo = std::numeric_limits<flow_type>::max();

  struct edge {
    int src;
    int dst;
    int rev;
    flow_type cap, flow;

    edge(int src, int dst, int rev, flow_type cap)
        : src(src), dst(dst), rev(rev), cap(cap), flow(0) {}
  };

  Dinic(int n) : adj(n), que(n), level(n), edge_pos(n) {}

  int add_edge(int src, int dst, flow_type cap, flow_type rcap = 0) {
    adj[src].emplace_back(src, dst, (int)adj[dst].size(), cap);
    if (src == dst)
      adj[src].back().rev++;
    adj[dst].emplace_back(dst, src, (int)adj[src].size() - 1, rcap);
    return (int)adj[src].size() - 1 - (src == dst);
  }

  result_type max_flow(int source, int sink) {
    result_type flow = 0;
    while (true) {
      int front = 0, back = 0;
      std::fill(level.begin(), level.end(), -1);
      for (level[que[back++] = sink] = 0; front < back && level[source] == -1;
           ++front) {
        int u = que[front];
        for (const edge &e : adj[u])
          if (level[e.dst] == -1 && rev(e).flow < rev(e).cap)
            level[que[back++] = e.dst] = 1 + level[u];
      }
      if (level[source] == -1)
        break;
      std::fill(edge_pos.begin(), edge_pos.end(), 0);
      std::function<flow_type(int, flow_type)> find_path = [&](int from,
                                                               flow_type res) {
        if (from == sink)
          return res;
        for (int &ept = edge_pos[from]; ept < (int)adj[from].size(); ++ept) {
          edge &e = adj[from][ept];
          if (e.flow == e.cap || level[e.dst] + 1 != level[from])
            continue;
          flow_type push = find_path(e.dst, std::min(res, e.cap - e.flow));
          if (push > 0) {
            e.flow += push;
            rev(e).flow -= push;
            if (e.flow == e.cap)
              ++ept;
            return push;
          }
        }
        return static_cast<flow_type>(0);
      };
      for (flow_type f; (f = find_path(source, oo)) > 0;)
        flow += f;
    }
    return flow;
  }

  std::vector<std::vector<edge>> adj;
  std::vector<int> que;
  std::vector<int> level;
  std::vector<int> edge_pos;

  inline edge &rev(const edge &e) { return adj[e.dst][e.rev]; }
};

int DIR4[4][2] = {{-1, 0}, {0, +1}, {+1, 0}, {0, -1}};

class VBoard {
public:
  int n, m;

  VBoard(int n = 0, int m = 0) : n(n), m(m) {}

  bool inside(int x, int y) { return 0 <= x && x < n && 0 <= y && y < m; }

  int index(int x, int y) { return x * m + y; }

  std::pair<int, int> from_index(int index) { return {index / m, index % m}; }
};

} // namespace asl

#include <tuple>

#include <random>

#include <utility>

#define endl '\n'

using namespace std;
using namespace asl;

void solve() {
  int n, m;
  cin >> n >> m;

  vec<string> b(n);
  cin >> b;

  Dinic<int> dinic(n * m + 2);

  auto brd = VBoard(n, n);

  int s = n * m, t = n * m + 1;

  for (int i = 0; i < n; ++i)
    for (int j = 0; j < m; ++j) {
      if (b[i][j] == '#')
        continue;

      int u = brd.index(i, j);

      if ((i + j) & 1) {
        dinic.add_edge(s, u, 1);

        for (auto [dx, dy] : DIR4) {
          int nx = i + dx, ny = j + dy;

          if (brd.inside(nx, ny) && b[nx][ny] == '.') {
            int v = brd.index(nx, ny);
            dinic.add_edge(u, v, 1);
          }
        }
      } else {
        dinic.add_edge(u, t, 1);
      }
    }

  auto res = dinic.max_flow(s, t);

  cout << res << endl;

  for (int i = 0; i < n; ++i)
    for (int j = 0; j < m; ++j) {
      if ((i + j) & 1) {
        int u = brd.index(i, j);

        for (auto e : dinic.adj[u]) {
          if (e.flow == 1) {
            int nx, ny;
            tie(nx, ny) = brd.from_index(e.dst);

            char A = '>', B = '<';
            if (i != nx)
              A = 'v', B = '^';
            if (make_pair(nx, ny) < make_pair(i, j))
              swap(A, B);
            b[i][j] = A;
            b[nx][ny] = B;
          }
        }
      }
    }

  for (auto row : b)
    cout << row << endl;
}

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

  int t = 1;

  for (int i = 1; i <= t; ++i) {
    solve();
  }

  return 0;
}


Fixed submission:
#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstring>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <istream>

#include <map>
#include <math.h>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include <stdint.h>

namespace asl {
template <typename T> using vec = std::vector<T>;

template <typename T>
std::istream &operator>>(std::istream &is, std::vector<T> &vec) {
  for (auto &value : vec)
    is >> value;
  return is;
}

} // namespace asl

#include <experimental/optional>

namespace asl {

template <typename C, typename R = C> class Dinic {
public:
  typedef C flow_type;
  typedef R result_type;

  static_assert(std::is_arithmetic<flow_type>::value,
                "flow_type must be arithmetic");
  static_assert(std::is_arithmetic<result_type>::value,
                "result_type must be arithmetic");

  static const flow_type oo = std::numeric_limits<flow_type>::max();

  struct edge {
    int src;
    int dst;
    int rev;
    flow_type cap, flow;

    edge(int src, int dst, int rev, flow_type cap)
        : src(src), dst(dst), rev(rev), cap(cap), flow(0) {}
  };

  Dinic(int n) : adj(n), que(n), level(n), edge_pos(n) {}

  int add_edge(int src, int dst, flow_type cap, flow_type rcap = 0) {
    adj[src].emplace_back(src, dst, (int)adj[dst].size(), cap);
    if (src == dst)
      adj[src].back().rev++;
    adj[dst].emplace_back(dst, src, (int)adj[src].size() - 1, rcap);
    return (int)adj[src].size() - 1 - (src == dst);
  }

  result_type max_flow(int source, int sink) {
    result_type flow = 0;
    while (true) {
      int front = 0, back = 0;
      std::fill(level.begin(), level.end(), -1);
      for (level[que[back++] = sink] = 0; front < back && level[source] == -1;
           ++front) {
        int u = que[front];
        for (const edge &e : adj[u])
          if (level[e.dst] == -1 && rev(e).flow < rev(e).cap)
            level[que[back++] = e.dst] = 1 + level[u];
      }
      if (level[source] == -1)
        break;
      std::fill(edge_pos.begin(), edge_pos.end(), 0);
      std::function<flow_type(int, flow_type)> find_path = [&](int from,
                                                               flow_type res) {
        if (from == sink)
          return res;
        for (int &ept = edge_pos[from]; ept < (int)adj[from].size(); ++ept) {
          edge &e = adj[from][ept];
          if (e.flow == e.cap || level[e.dst] + 1 != level[from])
            continue;
          flow_type push = find_path(e.dst, std::min(res, e.cap - e.flow));
          if (push > 0) {
            e.flow += push;
            rev(e).flow -= push;
            if (e.flow == e.cap)
              ++ept;
            return push;
          }
        }
        return static_cast<flow_type>(0);
      };
      for (flow_type f; (f = find_path(source, oo)) > 0;)
        flow += f;
    }
    return flow;
  }

  std::vector<std::vector<edge>> adj;
  std::vector<int> que;
  std::vector<int> level;
  std::vector<int> edge_pos;

  inline edge &rev(const edge &e) { return adj[e.dst][e.rev]; }
};

int DIR4[4][2] = {{-1, 0}, {0, +1}, {+1, 0}, {0, -1}};

class VBoard {
public:
  int n, m;

  VBoard(int n = 0, int m = 0) : n(n), m(m) {}

  bool inside(int x, int y) { return 0 <= x && x < n && 0 <= y && y < m; }

  int index(int x, int y) { return x * m + y; }

  std::pair<int, int> from_index(int index) { return {index / m, index % m}; }
};

} // namespace asl

#include <tuple>

#include <random>

#include <utility>

#define endl '\n'

using namespace std;
using namespace asl;

void solve() {
  int n, m;
  cin >> n >> m;

  vec<string> b(n);
  cin >> b;

  Dinic<int> dinic(n * m + 2);

  auto brd = VBoard(n, m);

  int s = n * m, t = n * m + 1;

  for (int i = 0; i < n; ++i)
    for (int j = 0; j < m; ++j) {
      if (b[i][j] == '#')
        continue;

      int u = brd.index(i, j);

      if ((i + j) & 1) {
        dinic.add_edge(s, u, 1);

        for (auto [dx, dy] : DIR4) {
          int nx = i + dx, ny = j + dy;

          if (brd.inside(nx, ny) && b[nx][ny] == '.') {
            int v = brd.index(nx, ny);
            dinic.add_edge(u, v, 1);
          }
        }
      } else {
        dinic.add_edge(u, t, 1);
      }
    }

  auto res = dinic.max_flow(s, t);

  cout << res << endl;

  for (int i = 0; i < n; ++i)
    for (int j = 0; j < m; ++j) {
      if ((i + j) & 1) {
        int u = brd.index(i, j);

        for (auto e : dinic.adj[u]) {
          if (e.flow == 1) {
            int nx, ny;
            tie(nx, ny) = brd.from_index(e.dst);

            char A = '>', B = '<';
            if (i != nx)
              A = 'v', B = '^';
            if (make_pair(nx, ny) < make_pair(i, j))
              swap(A, B);
            b[i][j] = A;
            b[nx][ny] = B;
          }
        }
      }
    }

  for (auto row : b)
    cout << row << endl;
}

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

  int t = 1;

  for (int i = 1; i <= t; ++i) {
    solve();
  }

  return 0;
}