Problem p02561 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
#define REP(i, n) for (int i = 0, i##_len = (n); i < i##_len; ++i)
#define FOR(i, a, b) for (int i = (a), i##_len = (b); i < i##_len; i++)
#define ALL(x) (x).begin(), (x).end() // sortなどの引数を省略したい
#ifdef _DEBUG
#define PRE_COMMAND                                                            \\
  std::cin.rdbuf(in.rdbuf());                                                  \\
  std::cout << fixed << setprecision(15);
#else
#define PRE_COMMAND cout << fixed << setprecision(15);
#endif
const double EPS = 1e-10, PI = acos(-1.0);
template <class T> auto MAX(T &seq) {
  return *max_element(seq.begin(), seq.end());
}
template <class T> auto MIN(T &seq) {
  return *min_element(seq.begin(), seq.end());
}
template <class T> auto SUM(T &seq) {
  T temp{0};
  auto &temp2 = temp[0];
  return accumulate(seq.begin(), seq.end(), temp2);
}
template <class T> void SORT(T &seq) { sort(seq.begin(), seq.end()); }
template <class T, class S> void SORT(T &seq, S &sort_order) {
  sort(seq.begin(), seq.end(), sort_order);
}
template <class T> void SORTR(vector<T> &seq) {
  sort(seq.begin(), seq.end(), greater<T>());
}
template <class T, class S, class R> long long pow(T n_0, S k_0, R mod_0) {
  long long n = n_0 % mod_0, k = k_0, mod = mod_0, now = 1;
  while (k) {
    if (k & 1)
      now = (now * n) % mod;
    n = (n * n) % mod;
    n >>= 1;
  }
  return now;
}
template <typename T> istream &operator>>(istream &is, vector<T> &vec) {
  for (T &x : vec)
    is >> x;
  return is;
}

// 頂点の数、辺の情報、indexed
template <class num_type> struct max_flow {
  struct edge {
    int to, rev;
    num_type cap;
    edge(int to_temp, ll cap_temp, int rev_temp)
        : to(to_temp), cap(cap_temp), rev(rev_temp) {}
  };
  int n, m = 0;              // 頂点数と辺数
  num_type inf = pow(10, 9); // 無限大
  vector<vector<edge>> g;    // 隣接グラフ
  vector<int> level, iter;   // 距離とどこまで検索終了しているか
  set<tuple<int, int>> edge_set; // 辺の集合
  // コンストラクタ
  max_flow(int n_temp) : n(n_temp) { g.assign(n, {}); }
  max_flow(int n_temp, vector<tuple<int, int, num_type>> g_temp) : n(n_temp) {
    int from, to;
    num_type cap;
    g.assign(n, {});
    for (tuple<int, int, num_type> t_temp : g_temp) {
      tie(from, to, cap) = t_temp;
      add_edge(from, to, cap);
    }
  }
  // 辺の追加
  int add_edge(int from, int to, num_type cap) {
    g[from].push_back((edge){to, cap, (int)g[to].size()});
    g[to].push_back((edge){from, 0, (int)g[from].size() - 1});
    edge_set.insert(make_tuple(from, to));
    return ++m;
  }
  // sからtへの最大流を計算
  num_type flow(int s, int t) {
    int f = 0, f2;
    for (;;) {
      bfs(s);
      if (level[t] < 0)
        return f;
      iter.assign(n, 0);
      while ((f2 = dfs(s, t, inf)) > 0) {
        f += f2;
      }
    }
  }
  // 残余グラフでsから到達できる頂点の集合を返す
  // flmake_tuple(from, to)ow(s, *)を流してから実行する
  vector<int> min_cut(int s) {
    vector<int> ret(n, 0);
    for (int i = 0; i < n; i++) {
      ret[i] = (int)(level[i] > -1);
    }
    return ret;
  }
  // 辺の状態を返す
  vector<vector<tuple<int, num_type>>> get_edges() {
    vector<vector<tuple<int, num_type>>> ret(n);
    int from, to, rev;
    num_type f;
    for (int from = 0; from < n; from++) {
      for (edge temp : g[from]) {
        to = temp.to;
        if (edge_set.count(make_tuple(from, to))) {
          ret[from].push_back(make_tuple(to, g[to][temp.rev].cap));
        }
      }
    }
    return ret;
  }
  // flow用のBFS関数
  void bfs(int s) {
    level.assign(n, -1);
    deque<int> que;
    level[s] = 0;
    que.push_back(s);
    while (!que.empty()) {
      int v = que.front();
      que.pop_front();
      for (int i = 0; i < (int)g[v].size(); i++) {
        edge &e = g[v][i];
        if (e.cap > 0 && level[e.to] < 0) {
          level[e.to] = level[v] + 1;
          que.push_back(e.to);
        }
      }
    }
  }
  // flow用のDFS関数
  int dfs(int v, int t, num_type f) {
    if (v == t)
      return f;
    for (int &i = iter[v]; i < (int)g[v].size(); i++) {
      edge &e = g[v][i];
      if (e.cap > 0 && level[v] < level[e.to]) {
        int f2 = dfs(e.to, t, min(f, e.cap));
        if (f2 > 0) {
          e.cap -= f2;
          g[e.to][e.rev].cap += f2;
          return f2;
        }
      }
    }
    return 0;
  }
};

// 最大マッチングを行う、最大フローのライブラリも一緒に持ってくる
// 入力：xのサイズ、yのサイズ、xy間の辺、indexed
vector<tuple<int, int>> bimatch(int x_size, int y_size,
                                vector<tuple<int, int>> xy) {
  int m = (int)xy.size(), n = x_size + y_size + 2;
  int m2 = x_size + y_size + m;
  vector<tuple<int, int, int>> edge(m2);
  for (int i = 0; i < m; i++) {
    int x, y;
    tie(x, y) = xy[i];
    edge[i] = make_tuple(x + 1, y + x_size + 1, 1);
  }
  for (int i = 0; i < x_size; i++) {
    edge[m + i] = make_tuple(0, i + 1, 1);
  }
  for (int i = 0; i < y_size; i++) {
    edge[m + x_size + i] = make_tuple(i + x_size + 1, n - 1, 1);
  }
  max_flow<int> flow(n, edge);
  flow.flow(0, n - 1);
  vector<vector<tuple<int, int>>> g = flow.get_edges();
  vector<tuple<int, int>> ret;
  for (int x = 1; x < (int)g.size(); x++) {
    int y, z, v;
    for (tuple<int, int> t : g[x]) {
      tie(y, v) = t;
      if (y == n - 1 || v == 0)
        continue;
      ret.push_back(make_tuple(x - 1, y - x_size - 1));
    }
  }
  return ret;
}

int main() {
  PRE_COMMAND
  int h, w, x, y;
  cin >> h >> w;
  vector<vector<char>> v_s(h, vector<char>(w));
  cin >> v_s;
  vector<tuple<int, int>> v_t;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      if ((i + j) % 2 || v_s[i][j] == '#') {
        continue;
      }
      x = i * w + j;
      if (i != 0 && v_s[i - 1][j] == '.')
        v_t.push_back(make_tuple(x, x - w));
      if (i != h - 1 && v_s[i + 1][j] == '.')
        v_t.push_back(make_tuple(x, x + w));
      if (j != 0 && v_s[i][j - 1] == '.')
        v_t.push_back(make_tuple(x, x - 1));
      if (j != w - 1 && v_s[i][j + 1] == '.')
        v_t.push_back(make_tuple(x, x + 1));
    }
  }
  for (int i = 0; i < (int)v_t.size(); i++) {
    tie(x, y) = v_t[i];
    v_t[i] = make_tuple(x / 2, y / 2);
  }
  map<int, tuple<int, int>> x_dict, y_dict;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      if ((i + j) % 2 == 0) {
        x_dict[(i * w + j) / 2] = make_tuple(i, j);
      } else {
        y_dict[(i * w + j) / 2] = make_tuple(i, j);
      }
    }
  }
  int y_size = h * w / 2;
  int x_size = h * w - y_size;
  vector<tuple<int, int>> b = bimatch(x_size, y_size, v_t);
  for (auto temp : b) {
    tie(x, y) = temp;
    int x0, x1, y0, y1;
    tie(x0, x1) = x_dict[x], tie(y0, y1) = y_dict[y];
    if (x0 == y0) {
      if (x1 > y1)
        swap(x1, y1);
      v_s[x0][x1] = '>';
      v_s[y0][y1] = '<';
    }
    if (x1 == y1) {
      if (x0 > y0)
        swap(x0, y0);
      v_s[x0][x1] = 'v';
      v_s[y0][y1] = '^';
    }
  }
  cout << b.size() << endl;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      cout << v_s[i][j];
    }
    cout << endl;
  }
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
#define REP(i, n) for (int i = 0, i##_len = (n); i < i##_len; ++i)
#define FOR(i, a, b) for (int i = (a), i##_len = (b); i < i##_len; i++)
#define ALL(x) (x).begin(), (x).end() // sortなどの引数を省略したい
#ifdef _DEBUG
#define PRE_COMMAND                                                            \\
  std::cin.rdbuf(in.rdbuf());                                                  \\
  std::cout << fixed << setprecision(15);
#else
#define PRE_COMMAND cout << fixed << setprecision(15);
#endif
const double EPS = 1e-10, PI = acos(-1.0);
template <class T> auto MAX(T &seq) {
  return *max_element(seq.begin(), seq.end());
}
template <class T> auto MIN(T &seq) {
  return *min_element(seq.begin(), seq.end());
}
template <class T> auto SUM(T &seq) {
  T temp{0};
  auto &temp2 = temp[0];
  return accumulate(seq.begin(), seq.end(), temp2);
}
template <class T> void SORT(T &seq) { sort(seq.begin(), seq.end()); }
template <class T, class S> void SORT(T &seq, S &sort_order) {
  sort(seq.begin(), seq.end(), sort_order);
}
template <class T> void SORTR(vector<T> &seq) {
  sort(seq.begin(), seq.end(), greater<T>());
}
template <class T, class S, class R> long long pow(T n_0, S k_0, R mod_0) {
  long long n = n_0 % mod_0, k = k_0, mod = mod_0, now = 1;
  while (k) {
    if (k & 1)
      now = (now * n) % mod;
    n = (n * n) % mod;
    n >>= 1;
  }
  return now;
}
template <typename T> istream &operator>>(istream &is, vector<T> &vec) {
  for (T &x : vec)
    is >> x;
  return is;
}

// 頂点の数、辺の情報、indexed
template <class num_type> struct max_flow {
  int n;
  num_type flow;
  vector<map<int, num_type>> g_temp, g;
  vector<vector<int>> gkey_temp;
  max_flow(int &t1, vector<tuple<int, int, num_type>> &t2, int indexed = 1) {
    int u, v;
    num_type w;
    n = t1;
    g_temp.resize(n);
    gkey_temp.resize(n);
    for (tuple<int, int, num_type> t3 : t2) {
      tie(u, v, w) = t3;
      add_edge(u - indexed, v - indexed, w);
    }
    for (u = 0; u < n; u++) {
      for (tuple<int, num_type> t3 : g_temp[u]) {
        tie(v, w) = t3;
        gkey_temp[u].push_back(v);
      }
    }
  }
  void add_edge(int From, int to, num_type &cap) {
    g_temp[From][to] = cap;
    g_temp[to][-From - 1] = 0;
  }
  // 最大流を計算する、gの中に実際のフローが入っている
  num_type calc_flow(int s, int t) {
    flow = 0;
    g = g_temp;
    vector<vector<int>> gkey = gkey_temp;
    while (true) {
      num_type inf = pow(10, 6);
      vector<bool> used(n, false);
      vector<int> used2(n, 0);
      vector<tuple<int, num_type>> q(1, make_tuple(s, inf));
      vector<num_type> ans = {0};
      while (q.size()) {
        int v;
        num_type f, a = ans[0];
        tie(v, f) = q.back();
        if (!a) {
          if (v == t) {
            ans[0] = f;
            continue;
          }
          map<int, num_type> gv = g[v];
          vector<int> gkv = gkey[v];
          int l = (int)gkv.size();
          used[v] = true;
          while (true) {
            int i = used2[v];
            used2[v]++;
            if (i < l) {
              int to = gkv[i];
              num_type cap = gv[to];
              if (to < 0) {
                to = -to - 1;
              }
              if ((!used[to]) && cap) {
                q.push_back(make_tuple(to, min(f, cap)));
                break;
              }
            } else {
              q.pop_back();
              ans[0] = 0;
              break;
            }
          }
        } else {
          q.pop_back();
          if (q.size()) {
            v = get<0>(q.back());
            int to = gkey[v][used2[v] - 1];
            g[v][to] -= a;
            if (to < 0) {
              to = -to - 1;
            } else {
              v = -v - 1;
            }
            g[to][v] += a;
          }
        }
      }
      if (!ans[0]) {
        return flow;
      }
      flow += ans[0];
    }
  }
};

// 最大マッチングを行う、最大フローのライブラリも一緒に持ってくる
// 入力：xのサイズ、yのサイズ、xy間の辺、indexed
vector<tuple<int, int>> bimatch(int x_size, int y_size,
                                vector<tuple<int, int>> xy, int indexed = 1) {
  int m = (int)xy.size(), n = x_size + y_size + 2;
  int m2 = x_size + y_size + m, hosei = 1 - indexed;
  vector<tuple<int, int, int>> edge(m2);
  for (int i = 0; i < m; i++) {
    int x, y;
    tie(x, y) = xy[i];
    edge[i] = make_tuple(x + hosei, y + hosei + x_size, 1);
  }
  for (int i = 0; i < x_size; i++) {
    edge[m + i] = make_tuple(0, i + 1, 1);
  }
  for (int i = 0; i < y_size; i++) {
    edge[m + x_size + i] = make_tuple(i + x_size + 1, n - 1, 1);
  }
  max_flow<int> flow(n, edge, 0);
  flow.calc_flow(0, n - 1);
  vector<map<int, int>> g = flow.g;
  vector<tuple<int, int>> ret;
  for (int x = 0; x < (int)g.size(); x++) {
    if (x == n - 1)
      continue;
    int y, z, v;
    for (auto t : g[x]) {
      tie(y, v) = t;
      if (v == 0 || y > -2)
        continue;
      ret.push_back(make_tuple(-y - 2 + indexed, x - x_size - 1 + indexed));
    }
  }
  return ret;
}

int main() {
  PRE_COMMAND
  int h, w, x, y;
  cin >> h >> w;
  vector<vector<char>> v_s(h, vector<char>(w));
  cin >> v_s;
  vector<tuple<int, int>> v_t;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      if ((i + j) % 2 || v_s[i][j] == '#') {
        continue;
      }
      x = i * w + j;
      if (i != 0 && v_s[i - 1][j] == '.')
        v_t.push_back(make_tuple(x, x - w));
      if (i != h - 1 && v_s[i + 1][j] == '.')
        v_t.push_back(make_tuple(x, x + w));
      if (j != 0 && v_s[i][j - 1] == '.')
        v_t.push_back(make_tuple(x, x - 1));
      if (j != w - 1 && v_s[i][j + 1] == '.')
        v_t.push_back(make_tuple(x, x + 1));
    }
  }
  for (int i = 0; i < (int)v_t.size(); i++) {
    tie(x, y) = v_t[i];
    v_t[i] = make_tuple(x / 2, y / 2);
  }
  map<int, tuple<int, int>> x_dict, y_dict;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      if ((i + j) % 2 == 0) {
        x_dict[(i * w + j) / 2] = make_tuple(i, j);
      } else {
        y_dict[(i * w + j) / 2] = make_tuple(i, j);
      }
    }
  }
  int y_size = h * w / 2;
  int x_size = h * w - y_size;
  vector<tuple<int, int>> b = bimatch(x_size, y_size, v_t, 0);
  for (auto temp : b) {
    tie(x, y) = temp;
    int x0, x1, y0, y1;
    tie(x0, x1) = x_dict[x], tie(y0, y1) = y_dict[y];
    if (x0 == y0) {
      if (x1 > y1)
        swap(x1, y1);
      v_s[x0][x1] = '>';
      v_s[y0][y1] = '<';
    }
    if (x1 == y1) {
      if (x0 > y0)
        swap(x0, y0);
      v_s[x0][x1] = 'v';
      v_s[y0][y1] = '^';
    }
  }
  cout << b.size() << endl;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      cout << v_s[i][j];
    }
    cout << endl;
  }
}