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

/**
 *
 */

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

using i8 = int8_t;
using u8 = uint8_t;
using i16 = int16_t;
using u16 = uint16_t;
using i32 = int32_t;
using u32 = uint32_t;
using i64 = int64_t;
using u64 = uint64_t;
#ifdef __SIZEOF_INT128__
using i128 = __int128;
using u128 = unsigned __int128;
#endif

using f32 = float;
using f64 = double;
using f80 = __float80;
using f128 = __float128;
// }}}

template <typename T> constexpr T PROCON_INF();
template <> constexpr i64 PROCON_INF<i64>() {
  return 1'010'000'000'000'000'000LL;
}
template <> constexpr f64 PROCON_INF<f64>() { return 1e100; }

constexpr i64 INF = PROCON_INF<i64>();
constexpr f64 FINF = PROCON_INF<f64>();

constexpr i64 MOD = 1'000'000'007LL;

constexpr f64 EPS = 1e-12;

constexpr f64 PI = 3.14159265358979323846;

// util {{{
#define FOR(i, start, end)                                                     \\
  for (i64 i = (start), i##_end = (end); i < i##_end; ++i)
#define REP(i, n) FOR(i, 0, n)

#define ALL(f, c, ...)                                                         \\
  (([&](decltype((c)) cccc) {                                                  \\
    return (f)(std::begin(cccc), std::end(cccc), ##__VA_ARGS__);               \\
  })(c))
#define SLICE(f, c, l, r, ...)                                                 \\
  (([&](decltype((c)) cccc, decltype((l)) llll, decltype((r)) rrrr) {          \\
    auto iiii = llll <= rrrr ? std::begin(cccc) + llll : std::end(cccc);       \\
    auto jjjj = llll <= rrrr ? std::begin(cccc) + rrrr : std::end(cccc);       \\
    return (f)(iiii, jjjj, ##__VA_ARGS__);                                     \\
  })(c, l, r))

#define GENERIC(f)                                                             \\
  ([](auto &&...args) -> decltype(auto) {                                      \\
    return (f)(std::forward<decltype(args)>(args)...);                         \\
  })

// BoolArray {{{
class BoolArray {
public:
  using value_type = bool;
  using reference = value_type &;
  using const_reference = const value_type &;
  using iterator = value_type *;
  using const_iterator = const value_type *;
  using difference_type = ptrdiff_t;
  using size_type = size_t;

  using reverse_iterator = std::reverse_iterator<iterator>;
  using const_reverse_iterator = std::reverse_iterator<const_iterator>;

  BoolArray() : BoolArray(0) {}
  explicit BoolArray(size_t n) : BoolArray(n, false) {}
  BoolArray(size_t n, bool value) : size_(n), data_(new bool[n]) {
    ALL(fill, *this, value);
  }

  BoolArray(initializer_list<bool> init)
      : size_(init.size()), data_(new bool[size_]) {
    ALL(copy, init, begin());
  }

  template <typename InputIt> BoolArray(InputIt first, InputIt last) {
    deque<bool> tmp(first, last);
    size_ = tmp.size();
    data_ = new bool[size_];
    ALL(copy, tmp, begin());
  }

  BoolArray(const BoolArray &other)
      : size_(other.size_), data_(new bool[size_]) {
    ALL(copy, other, begin());
  }

  BoolArray(BoolArray &&other) noexcept
      : size_(other.size_), data_(other.data_) {
    other.data_ = nullptr;
  }

  BoolArray &operator=(const BoolArray &other) {
    if (this == &other)
      return *this;
    if (!data_ || size_ < other.size_) {
      delete[] data_;
      data_ = new bool[other.size_];
    }
    size_ = other.size_;
    ALL(copy, other, begin());
    return *this;
  }

  BoolArray &operator=(BoolArray &&other) noexcept {
    if (this == &other)
      return *this;
    size_ = other.size_;
    data_ = other.data_;
    other.data_ = nullptr;
  }

  BoolArray &operator=(initializer_list<bool> init) {
    if (!data_ || size_ < init.size()) {
      delete[] data_;
      data_ = new bool[init.size()];
    }
    size_ = init.size();
    ALL(copy, init, begin());
    return *this;
  }

  void swap(BoolArray &other) noexcept {
    std::swap(size_, other.size_);
    std::swap(data_, other.data_);
  }

  ~BoolArray() {
    delete[] data_;
    data_ = nullptr;
  }

  bool empty() const noexcept { return size_ == 0; }
  size_type size() const noexcept { return size_; }
  size_type max_size() const noexcept { return 1'010'000'000; }

  iterator begin() noexcept { return data_; }
  const_iterator begin() const noexcept { return data_; }
  const_iterator cbegin() const noexcept { return data_; }

  iterator end() noexcept { return data_ + size_; }
  const_iterator end() const noexcept { return data_ + size_; }
  const_iterator cend() const noexcept { return data_ + size_; }

  reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
  const_reverse_iterator rbegin() const noexcept {
    return const_reverse_iterator(end());
  }
  const_reverse_iterator crbegin() const noexcept {
    return const_reverse_iterator(end());
  }

  reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
  const_reverse_iterator rend() const noexcept {
    return const_reverse_iterator(begin());
  }
  const_reverse_iterator crend() const noexcept {
    return const_reverse_iterator(begin());
  }

  reference operator[](size_type pos) { return data_[pos]; }
  const_reference operator[](size_type pos) const { return data_[pos]; }

  bool *data() noexcept { return data_; }
  const bool *data() const noexcept { return data_; }

private:
  size_t size_;
  bool *data_;
};

void swap(BoolArray &lhs, BoolArray &rhs) noexcept { lhs.swap(rhs); }

bool operator==(const BoolArray &lhs, const BoolArray &rhs) {
  return equal(begin(lhs), end(lhs), begin(rhs), end(rhs));
}
bool operator!=(const BoolArray &lhs, const BoolArray &rhs) {
  return !(lhs == rhs);
}

bool operator<(const BoolArray &lhs, const BoolArray &rhs) {
  return lexicographical_compare(begin(lhs), end(lhs), begin(rhs), end(rhs));
}
bool operator>(const BoolArray &lhs, const BoolArray &rhs) { return rhs < lhs; }
bool operator<=(const BoolArray &lhs, const BoolArray &rhs) {
  return !(rhs < lhs);
}
bool operator>=(const BoolArray &lhs, const BoolArray &rhs) {
  return !(lhs < rhs);
}
// }}}

// 多次元 vector {{{
// 最内周が vector<bool> になるのを避けるための措置
template <typename T> struct Array1Container {
  using type = vector<T>;
};
template <> struct Array1Container<bool> {
  using type = BoolArray;
};

// イテレート用
template <typename T> struct is_arrayn_container {
  static constexpr bool value = false;
};
template <typename T> struct is_arrayn_container<vector<T>> {
  static constexpr bool value = true;
};
template <> struct is_arrayn_container<BoolArray> {
  static constexpr bool value = true;
};

template <typename T> auto arrayn_make(i64 n, T x) {
  using Cont = typename Array1Container<T>::type;
  return Cont(n, x);
}

template <typename T, typename... Args,
          enable_if_t<2 <= sizeof...(Args), nullptr_t> = nullptr>
auto arrayn_make(i64 n, Args... args) {
  auto inner = arrayn_make<T>(args...);
  return vector<decltype(inner)>(n, inner);
}

template <typename T, typename F>
enable_if_t<!is_arrayn_container<T>::value> arrayn_foreach(T &e, F f) {
  f(e);
}

template <typename T, typename F>
enable_if_t<is_arrayn_container<T>::value> arrayn_foreach(T &ary, F f) {
  for (auto &e : ary)
    arrayn_foreach(e, f);
}

template <typename T, typename U>
enable_if_t<is_arrayn_container<T>::value> arrayn_fill(T &ary, const U &x) {
  arrayn_foreach(ary, [&x](auto &e) { e = x; });
}
// }}}

// 多次元生配列 {{{
template <typename T, typename F>
enable_if_t<rank<T>::value == 0> CARRAY_FOREACH(T &e, F f) {
  f(e);
}

template <typename Array, typename F>
enable_if_t<rank<Array>::value != 0> CARRAY_FOREACH(Array &ary, F f) {
  for (auto &e : ary)
    CARRAY_FOREACH(e, f);
}

template <typename Array, typename U>
enable_if_t<rank<Array>::value != 0> CARRAY_FILL(Array &ary, const U &v) {
  CARRAY_FOREACH(ary, [&v](auto &e) { e = v; });
}
// }}}

// メモ化ラッパー (8引数まで) {{{
template <i64 N1, typename F> class Memoized1 {
  static_assert(N1 >= 1, "");

public:
  explicit Memoized1(F &&f) : f_(forward<F>(f)) {}
  decltype(auto) operator()(i64 x1) const {
    using R = decltype(f_(*this, x1));
    static bool done[N1]{};
    static R memo[N1];
    if (!done[x1]) {
      memo[x1] = f_(*this, x1);
      done[x1] = true;
    }
    return memo[x1];
  }

private:
  const F f_;
};

template <i64 N1, i64 N2, typename F> class Memoized2 {
  static_assert(N1 >= 1 && N2 >= 1, "");

public:
  explicit Memoized2(F &&f) : f_(forward<F>(f)) {}
  decltype(auto) operator()(i64 x1, i64 x2) const {
    using R = decltype(f_(*this, x1, x2));
    static bool done[N1][N2]{};
    static R memo[N1][N2];
    if (!done[x1][x2]) {
      memo[x1][x2] = f_(*this, x1, x2);
      done[x1][x2] = true;
    }
    return memo[x1][x2];
  }

private:
  const F f_;
};

template <i64 N1, i64 N2, i64 N3, typename F> class Memoized3 {
  static_assert(N1 >= 1 && N2 >= 1 && N3 >= 1, "");

public:
  explicit Memoized3(F &&f) : f_(forward<F>(f)) {}
  decltype(auto) operator()(i64 x1, i64 x2, i64 x3) const {
    using R = decltype(f_(*this, x1, x2, x3));
    static bool done[N1][N2][N3]{};
    static R memo[N1][N2][N3];
    if (!done[x1][x2][x3]) {
      memo[x1][x2][x3] = f_(*this, x1, x2, x3);
      done[x1][x2][x3] = true;
    }
    return memo[x1][x2][x3];
  }

private:
  const F f_;
};

template <i64 N1, i64 N2, i64 N3, i64 N4, typename F> class Memoized4 {
  static_assert(N1 >= 1 && N2 >= 1 && N3 >= 1 && N4 >= 1, "");

public:
  explicit Memoized4(F &&f) : f_(forward<F>(f)) {}
  decltype(auto) operator()(i64 x1, i64 x2, i64 x3, i64 x4) const {
    using R = decltype(f_(*this, x1, x2, x3, x4));
    static bool done[N1][N2][N3][N4]{};
    static R memo[N1][N2][N3][N4];
    if (!done[x1][x2][x3][x4]) {
      memo[x1][x2][x3][x4] = f_(*this, x1, x2, x3, x4);
      done[x1][x2][x3][x4] = true;
    }
    return memo[x1][x2][x3][x4];
  }

private:
  const F f_;
};

template <i64 N1, i64 N2, i64 N3, i64 N4, i64 N5, typename F> class Memoized5 {
  static_assert(N1 >= 1 && N2 >= 1 && N3 >= 1 && N4 >= 1 && N5 >= 1, "");

public:
  explicit Memoized5(F &&f) : f_(forward<F>(f)) {}
  decltype(auto) operator()(i64 x1, i64 x2, i64 x3, i64 x4, i64 x5) const {
    using R = decltype(f_(*this, x1, x2, x3, x4, x5));
    static bool done[N1][N2][N3][N4][N5]{};
    static R memo[N1][N2][N3][N4][N5];
    if (!done[x1][x2][x3][x4][x5]) {
      memo[x1][x2][x3][x4][x5] = f_(*this, x1, x2, x3, x4, x5);
      done[x1][x2][x3][x4][x5] = true;
    }
    return memo[x1][x2][x3][x4][x5];
  }

private:
  const F f_;
};

template <i64 N1, i64 N2, i64 N3, i64 N4, i64 N5, i64 N6, typename F>
class Memoized6 {
  static_assert(N1 >= 1 && N2 >= 1 && N3 >= 1 && N4 >= 1 && N5 >= 1 && N6 >= 1,
                "");

public:
  explicit Memoized6(F &&f) : f_(forward<F>(f)) {}
  decltype(auto) operator()(i64 x1, i64 x2, i64 x3, i64 x4, i64 x5,
                            i64 x6) const {
    using R = decltype(f_(*this, x1, x2, x3, x4, x5, x6));
    static bool done[N1][N2][N3][N4][N5][N6]{};
    static R memo[N1][N2][N3][N4][N5][N6];
    if (!done[x1][x2][x3][x4][x5][x6]) {
      memo[x1][x2][x3][x4][x5][x6] = f_(*this, x1, x2, x3, x4, x5, x6);
      done[x1][x2][x3][x4][x5][x6] = true;
    }
    return memo[x1][x2][x3][x4][x5][x6];
  }

private:
  const F f_;
};

template <i64 N1, i64 N2, i64 N3, i64 N4, i64 N5, i64 N6, i64 N7, typename F>
class Memoized7 {
  static_assert(N1 >= 1 && N2 >= 1 && N3 >= 1 && N4 >= 1 && N5 >= 1 &&
                    N6 >= 1 && N7 >= 1,
                "");

public:
  explicit Memoized7(F &&f) : f_(forward<F>(f)) {}
  decltype(auto) operator()(i64 x1, i64 x2, i64 x3, i64 x4, i64 x5, i64 x6,
                            i64 x7) const {
    using R = decltype(f_(*this, x1, x2, x3, x4, x5, x6, x7));
    static bool done[N1][N2][N3][N4][N5][N6][N7]{};
    static R memo[N1][N2][N3][N4][N5][N6][N7];
    if (!done[x1][x2][x3][x4][x5][x6][x7]) {
      memo[x1][x2][x3][x4][x5][x6][x7] = f_(*this, x1, x2, x3, x4, x5, x6, x7);
      done[x1][x2][x3][x4][x5][x6][x7] = true;
    }
    return memo[x1][x2][x3][x4][x5][x6][x7];
  }

private:
  const F f_;
};

template <i64 N1, i64 N2, i64 N3, i64 N4, i64 N5, i64 N6, i64 N7, i64 N8,
          typename F>
class Memoized8 {
  static_assert(N1 >= 1 && N2 >= 1 && N3 >= 1 && N4 >= 1 && N5 >= 1 &&
                    N6 >= 1 && N7 >= 1 && N8 >= 1,
                "");

public:
  explicit Memoized8(F &&f) : f_(forward<F>(f)) {}
  decltype(auto) operator()(i64 x1, i64 x2, i64 x3, i64 x4, i64 x5, i64 x6,
                            i64 x7, i64 x8) const {
    using R = decltype(f_(*this, x1, x2, x3, x4, x5, x6, x7, x8));
    static bool done[N1][N2][N3][N4][N5][N6][N7][N8]{};
    static R memo[N1][N2][N3][N4][N5][N6][N7][N8];
    if (!done[x1][x2][x3][x4][x5][x6][x7][x8]) {
      memo[x1][x2][x3][x4][x5][x6][x7][x8] =
          f_(*this, x1, x2, x3, x4, x5, x6, x7, x8);
      done[x1][x2][x3][x4][x5][x6][x7][x8] = true;
    }
    return memo[x1][x2][x3][x4][x5][x6][x7][x8];
  }

private:
  const F f_;
};

template <i64 N1, typename F> decltype(auto) MEMOIZE(F &&f) {
  return Memoized1<N1, F>(forward<F>(f));
}
template <i64 N1, i64 N2, typename F> decltype(auto) MEMOIZE(F &&f) {
  return Memoized2<N1, N2, F>(forward<F>(f));
}
template <i64 N1, i64 N2, i64 N3, typename F> decltype(auto) MEMOIZE(F &&f) {
  return Memoized3<N1, N2, N3, F>(forward<F>(f));
}
template <i64 N1, i64 N2, i64 N3, i64 N4, typename F>
decltype(auto) MEMOIZE(F &&f) {
  return Memoized4<N1, N2, N3, N4, F>(forward<F>(f));
}
template <i64 N1, i64 N2, i64 N3, i64 N4, i64 N5, typename F>
decltype(auto) MEMOIZE(F &&f) {
  return Memoized5<N1, N2, N3, N4, N5, F>(forward<F>(f));
}
template <i64 N1, i64 N2, i64 N3, i64 N4, i64 N5, i64 N6, typename F>
decltype(auto) MEMOIZE(F &&f) {
  return Memoized6<N1, N2, N3, N4, N5, N6, F>(forward<F>(f));
}
template <i64 N1, i64 N2, i64 N3, i64 N4, i64 N5, i64 N6, i64 N7, typename F>
decltype(auto) MEMOIZE(F &&f) {
  return Memoized7<N1, N2, N3, N4, N5, N6, N7, F>(forward<F>(f));
}
template <i64 N1, i64 N2, i64 N3, i64 N4, i64 N5, i64 N6, i64 N7, i64 N8,
          typename F>
decltype(auto) MEMOIZE(F &&f) {
  return Memoized8<N1, N2, N3, N4, N5, N6, N7, N8, F>(forward<F>(f));
}

// }}}

// lambda で再帰 {{{
template <typename F> class FixPoint {
public:
  explicit constexpr FixPoint(F &&f) : f_(forward<F>(f)) {}

  template <typename... Args>
  constexpr decltype(auto) operator()(Args &&...args) const {
    return f_(*this, forward<Args>(args)...);
  }

private:
  const F f_;
};

template <typename F> decltype(auto) FIX(F &&f) {
  return FixPoint<F>(forward<F>(f));
}
// }}}

// tuple {{{
template <typename... TS, enable_if_t<0 < sizeof...(TS), nullptr_t> = nullptr>
constexpr auto tuple_head(const tuple<TS...> &t) {
  return get<0>(t);
}

template <typename... TS, size_t i, size_t... is>
constexpr auto tuple_tail_helper(const tuple<TS...> &t,
                                 index_sequence<i, is...>) {
  return make_tuple(get<is>(t)...);
}

template <typename... TS, enable_if_t<1 == sizeof...(TS), nullptr_t> = nullptr>
constexpr auto tuple_tail(const tuple<TS...> &) {
  return make_tuple();
}

template <typename... TS, enable_if_t<1 < sizeof...(TS), nullptr_t> = nullptr>
constexpr auto tuple_tail(const tuple<TS...> &t) {
  return tuple_tail_helper(t, make_index_sequence<sizeof...(TS)>());
}
// }}}

template <typename C> i64 SIZE(const C &c) {
  return static_cast<i64>(c.size());
}

template <typename T, size_t N> i64 SIZE(const T (&)[N]) {
  return static_cast<i64>(N);
}

bool is_odd(i64 x) { return x % 2 != 0; }
bool is_even(i64 x) { return x % 2 == 0; }

template <typename T> i64 cmp(T x, T y) { return (y < x) - (x < y); }
template <typename T> i64 sgn(T x) { return cmp(x, T(0)); }

i64 ipow(i64 x, i64 e) {
  assert(e >= 0);
  i64 res = 1;
  REP(_, e) { res *= x; }
  return res;
}

// 0 <= ilog2(x) <= 62
i64 ilog2(i64 x) {
  assert(x > 0);
  return 63 - __builtin_clzll(x);
}

// 0 <= ilog10(x) <= 18
i64 ilog10(i64 x) {
  assert(x > 0);
  static constexpr i64 TABLE[18]{
      9LL,
      99LL,
      999LL,
      9999LL,
      99999LL,
      999999LL,
      9999999LL,
      99999999LL,
      999999999LL,
      9999999999LL,
      99999999999LL,
      999999999999LL,
      9999999999999LL,
      99999999999999LL,
      999999999999999LL,
      9999999999999999LL,
      99999999999999999LL,
      999999999999999999LL,
  };
  REP(i, SIZE(TABLE)) {
    if (x <= TABLE[i])
      return i;
  }
  return SIZE(TABLE);
}

// Haskell の divMod と同じ
pair<i64, i64> divmod(i64 a, i64 b) {
  i64 q = a / b;
  i64 r = a % b;
  if ((b > 0 && r < 0) || (b < 0 && r > 0)) {
    --q;
    r += b;
  }
  return {q, r};
}

i64 div_ceil(i64 a, i64 b) {
  i64 q = a / b;
  i64 r = a % b;
  if ((b > 0 && r > 0) || (b < 0 && r < 0))
    ++q;
  return q;
}

i64 div_floor(i64 a, i64 b) { return divmod(a, b).first; }

i64 modulo(i64 a, i64 b) { return divmod(a, b).second; }

bool feq(f64 x, f64 y, f64 eps = EPS) { return fabs(x - y) < eps; }

template <typename T, typename U> bool chmax(T &xmax, const U &x) {
  if (xmax < x) {
    xmax = x;
    return true;
  }
  return false;
}

template <typename T, typename U> bool chmin(T &xmin, const U &x) {
  if (x < xmin) {
    xmin = x;
    return true;
  }
  return false;
}

template <typename ForwardIt, typename T, typename Comp = less<>>
ForwardIt bsearch_find(ForwardIt first, ForwardIt last, const T &x,
                       Comp comp = {}) {
  auto it = lower_bound(first, last, x, comp);
  if (it == last || comp(x, *it))
    return last;
  return it;
}

// x 未満の最後の要素
template <typename BidiIt, typename T, typename Comp = less<>>
BidiIt bsearch_lt(BidiIt first, BidiIt last, const T &x, Comp comp = {}) {
  auto it = lower_bound(first, last, x, comp);
  if (it == first)
    return last;
  return prev(it);
}

// x 以下の最後の要素
template <typename BidiIt, typename T, typename Comp = less<>>
BidiIt bsearch_le(BidiIt first, BidiIt last, const T &x, Comp comp = {}) {
  auto it = upper_bound(first, last, x, comp);
  if (it == first)
    return last;
  return prev(it);
}

// x より大きい最初の要素
template <typename BidiIt, typename T, typename Comp = less<>>
BidiIt bsearch_gt(BidiIt first, BidiIt last, const T &x, Comp comp = {}) {
  return upper_bound(first, last, x, comp);
}

// x 以上の最初の要素
template <typename BidiIt, typename T, typename Comp = less<>>
BidiIt bsearch_ge(BidiIt first, BidiIt last, const T &x, Comp comp = {}) {
  return lower_bound(first, last, x, comp);
}

template <typename InputIt> auto SUM(InputIt first, InputIt last) {
  using T = typename iterator_traits<InputIt>::value_type;
  return accumulate(first, last, T());
}

template <typename ForwardIt, typename UnaryOperation>
ForwardIt transform_self(ForwardIt first, ForwardIt last, UnaryOperation op) {
  return transform(first, last, first, op);
}

template <typename C> void UNIQ(C &c) { c.erase(ALL(unique, c), end(c)); }

template <typename BinaryFunc, typename UnaryFunc>
auto ON(BinaryFunc bf, UnaryFunc uf) {
  return [bf, uf](const auto &x, const auto &y) { return bf(uf(x), uf(y)); };
}

template <typename F> auto LT_ON(F f) { return ON(less<>(), f); }

template <typename F> auto GT_ON(F f) { return ON(greater<>(), f); }

struct IDENTITY {
  template <typename T> constexpr T &&operator()(T &&x) const noexcept {
    return forward<T>(x);
  }
};

char digit_chr(i64 n) { return static_cast<char>('0' + n); }

i64 digit_ord(char c) { return c - '0'; }

char lower_chr(i64 n) { return static_cast<char>('a' + n); }

i64 lower_ord(char c) { return c - 'a'; }

char upper_chr(i64 n) { return static_cast<char>('A' + n); }

i64 upper_ord(char c) { return c - 'A'; }

// 出力は operator<< を直接使わず、このテンプレート経由で行う
// 提出用出力とデバッグ用出力を分けるため
template <typename T> struct Formatter {
  static ostream &write_str(ostream &out, const T &x) { return out << x; }
  static ostream &write_repr(ostream &out, const T &x) { return out << x; }
};

template <typename T> ostream &WRITE_STR(ostream &out, const T &x) {
  return Formatter<T>::write_str(out, x);
}

template <typename T> ostream &WRITE_REPR(ostream &out, const T &x) {
  return Formatter<T>::write_repr(out, x);
}

template <typename InputIt>
ostream &WRITE_JOIN_STR(ostream &out, InputIt first, InputIt last,
                        const string &sep) {
  while (first != last) {
    WRITE_STR(out, *first++);
    if (first != last)
      out << sep;
  }
  return out;
}

template <typename InputIt>
ostream &WRITE_JOIN_REPR(ostream &out, InputIt first, InputIt last,
                         const string &sep) {
  while (first != last) {
    WRITE_REPR(out, *first++);
    if (first != last)
      out << sep;
  }
  return out;
}

template <typename InputIt>
ostream &WRITE_RANGE_STR(ostream &out, InputIt first, InputIt last) {
  return WRITE_JOIN_STR(out, first, last, " ");
}

template <typename InputIt>
ostream &WRITE_RANGE_REPR(ostream &out, InputIt first, InputIt last) {
  out << "[";
  WRITE_JOIN_REPR(out, first, last, ", ");
  out << "]";
  return out;
}

template <typename T> void FROM_STR(const string &s, T &x) {
  istringstream in(s);
  in >> x;
}

template <typename T> string TO_STR(const T &x) {
  ostringstream out;
  WRITE_STR(out, x);
  return out.str();
}

template <typename T> string TO_REPR(const T &x) {
  ostringstream out;
  WRITE_REPR(out, x);
  return out.str();
}

template <typename InputIt> string RANGE_TO_STR(InputIt first, InputIt last) {
  ostringstream out;
  WRITE_RANGE_STR(out, first, last);
  return out.str();
}

template <typename InputIt> string RANGE_TO_REPR(InputIt first, InputIt last) {
  ostringstream out;
  WRITE_RANGE_REPR(out, first, last);
  return out.str();
}

template <typename InputIt>
string JOIN(InputIt first, InputIt last, const string &sep) {
  ostringstream out;
  WRITE_JOIN_STR(out, first, last, sep);
  return out.str();
}

template <> struct Formatter<i64> {
  static ostream &write_str(ostream &out, i64 x) { return out << x; }
  static ostream &write_repr(ostream &out, i64 x) {
    if (x == INF)
      return out << "INF";
    if (x == -INF)
      return out << "-INF";
    return out << x;
  }
};

template <> struct Formatter<f64> {
  static ostream &write_str(ostream &out, f64 x) { return out << x; }
  static ostream &write_repr(ostream &out, f64 x) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
    if (x == FINF)
      return out << "FINF";
    if (x == -FINF)
      return out << "-FINF";
#pragma GCC diagnostic pop
    return out << x;
  }
};

template <typename T> struct Formatter<vector<T>> {
  static ostream &write_str(ostream &out, const vector<T> &v) {
    return WRITE_RANGE_STR(out, begin(v), end(v));
  }
  static ostream &write_repr(ostream &out, const vector<T> &v) {
    out << "vector";
    return WRITE_RANGE_REPR(out, begin(v), end(v));
  }
};

template <> struct Formatter<BoolArray> {
  static ostream &write_str(ostream &out, const BoolArray &a) {
    return WRITE_RANGE_STR(out, begin(a), end(a));
  }
  static ostream &write_repr(ostream &out, const BoolArray &a) {
    out << "BoolArray";
    return WRITE_RANGE_REPR(out, begin(a), end(a));
  }
};

template <typename T1, typename T2> struct Formatter<pair<T1, T2>> {
  static ostream &write_str(ostream &out, const pair<T1, T2> &p) {
    WRITE_STR(out, p.first);
    out << ' ';
    WRITE_STR(out, p.second);
    return out;
  }
  static ostream &write_repr(ostream &out, const pair<T1, T2> &p) {
    out << "(";
    WRITE_REPR(out, p.first);
    out << ",";
    WRITE_REPR(out, p.second);
    out << ")";
    return out;
  }
};

template <typename... TS> struct Formatter<tuple<TS...>> {
  template <size_t I = 0, enable_if_t<I == sizeof...(TS), nullptr_t> = nullptr>
  static ostream &write_str_impl(ostream &out, const tuple<TS...> &) {
    return out;
  }
  template <size_t I = 0,
            enable_if_t<I<sizeof...(TS), nullptr_t> = nullptr> static ostream
                &write_str_impl(ostream &out, const tuple<TS...> &t) {
    if (I != 0)
      out << ' ';
    WRITE_STR(out, get<I>(t));
    return write_str_impl<I + 1>(out, t);
  }

  template <size_t I = 0, enable_if_t<I == sizeof...(TS), nullptr_t> = nullptr>
  static ostream &write_repr_impl(ostream &out, const tuple<TS...> &) {
    if (sizeof...(TS) == 0)
      out << "(";
    return out << ")";
  }
  template <size_t I = 0,
            enable_if_t<I<sizeof...(TS), nullptr_t> = nullptr> static ostream
                &write_repr_impl(ostream &out, const tuple<TS...> &t) {
    if (I == 0)
      out << "(";
    else
      out << ",";
    WRITE_REPR(out, get<I>(t));
    return write_repr_impl<I + 1>(out, t);
  }

  static ostream &write_str(ostream &out, const tuple<TS...> &t) {
    return write_str_impl(out, t);
  }
  static ostream &write_repr(ostream &out, const tuple<TS...> &t) {
    return write_repr_impl(out, t);
  }
};

template <typename T> void RD(T &x) {
  cin >> x;
#ifdef PROCON_LOCAL
  assert(cin);
#endif
}

template <typename T> auto RD_ARRAY(i64 n) {
  auto res = arrayn_make<T>(n, T());
  arrayn_foreach(res, [](T &e) { RD(e); });
  return res;
}

template <typename T> auto RD_ARRAY2(i64 h, i64 w) {
  auto res = arrayn_make<T>(h, w, T());
  arrayn_foreach(res, [](T &e) { RD(e); });
  return res;
}

template <typename T1, typename T2> pair<T1, T2> RD_PAIR() {
  T1 x;
  RD(x);
  T2 y;
  RD(y);
  return {x, y};
}

template <typename... TS, enable_if_t<0 == sizeof...(TS), nullptr_t> = nullptr>
auto RD_TUPLE() {
  return make_tuple();
}

template <typename T, typename... TS> auto RD_TUPLE() {
  T x;
  RD(x);
  return tuple_cat(make_tuple(x), RD_TUPLE<TS...>());
}

void PRINT() {}

template <typename T, typename... TS>
void PRINT(const T &x, const TS &...args) {
  WRITE_STR(cout, x);
  if (sizeof...(args)) {
    cout << ' ';
    PRINT(args...);
  }
}

template <typename... TS> void PRINTLN(const TS &...args) {
  PRINT(args...);
  cout << '\\n';
}

[[noreturn]] void EXIT() {
#ifdef PROCON_LOCAL
  cerr.flush();
#endif
  cout.flush();
  _Exit(0);
}

template <typename T>
void DBG_IMPL(i64 line, const char *expr, const T &value) {
#ifdef PROCON_LOCAL
  cerr << "[L " << line << "]: ";
  cerr << expr << " = ";
  WRITE_REPR(cerr, value);
  cerr << "\\n";
#endif
}

template <typename T, size_t N>
void DBG_CARRAY_IMPL(i64 line, const char *expr, const T (&ary)[N]) {
#ifdef PROCON_LOCAL
  cerr << "[L " << line << "]: ";
  cerr << expr << " = ";
  WRITE_RANGE_REPR(cerr, begin(ary), end(ary));
  cerr << "\\n";
#endif
}

template <typename InputIt>
void DBG_RANGE_IMPL(i64 line, const char *expr1, const char *expr2,
                    InputIt first, InputIt last) {
#ifdef PROCON_LOCAL
  cerr << "[L " << line << "]: ";
  cerr << expr1 << "," << expr2 << " = ";
  WRITE_RANGE_REPR(cerr, first, last);
  cerr << "\\n";
#endif
}

#define DBG(expr) DBG_IMPL(__LINE__, #expr, (expr))
#define DBG_CARRAY(expr) DBG_CARRAY_IMPL(__LINE__, #expr, (expr))
#define DBG_RANGE(first, last)                                                 \\
  DBG_RANGE_IMPL(__LINE__, #first, #last, (first), (last))

#define PAIR make_pair
#define TUPLE make_tuple
// }}}

// init {{{
struct ProconInit {
  static constexpr int IOS_PREC = 15;
  static constexpr bool AUTOFLUSH = false;

  ProconInit() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(IOS_PREC);
#ifdef PROCON_LOCAL
    cerr << fixed << setprecision(IOS_PREC);
#endif
    if (AUTOFLUSH)
      cout << unitbuf;
  }
} PROCON_INIT;
// }}}

//--------------------------------------------------------------------

void solve() {
  i64 N;
  RD(N);
  i64 M;
  RD(M);

  auto G = arrayn_make<i64>(N, N, 0);
  REP(_, M) {
    i64 from, to;
    RD(from);
    RD(to);
    RD(G[from][to]);
  }
  // DBG(G);

  BoolArray visited(N);
  auto rec = FIX([N, &G, &visited](auto self, i64 v, i64 t, i64 f) -> i64 {
    if (v == t)
      return f;

    visited[v] = true;
    REP(to, N) {
      if (visited[to])
        continue;
      if (G[v][to] == 0)
        continue;
      i64 f2 = self(to, t, min(f, G[v][to]));
      if (f2 > 0) {
        G[v][to] -= f2;
        G[to][v] += f2;
        return f2;
      }
    }
    return 0;
  });

  i64 ans = 0;
  for (;;) {
    ALL(fill, visited, false);
    i64 f = rec(0, N - 1, INF);
    if (f == 0)
      break;
    ans += f;
  }

  // * 小さいケースで試した?
  // * 無効値 INF をそのまま出力してない?
  // * MOD はとった?
  // * 入出力の 0-based/1-based 確認した?
  // * 時間/メモリ制限は確認した?
  // * 違うやつ提出してない?
  // * 違うやつテストしてない?
  PRINTLN(ans);
}

signed main() {

  solve();

  EXIT();
}


Error: TLE

Fixed submission:

/**
 * 単純な貪欲法 (WA)
 */

// #include {{{
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cfloat>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <forward_list>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <regex>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#ifdef LOCAL
#include <fmt/format.h>
#include <fmt/ostream.h>
#endif

using namespace std;
// }}}

// type {{{
using i8 = int8_t;
using u8 = uint8_t;
using i16 = int16_t;
using u16 = uint16_t;
using i32 = int32_t;
using u32 = uint32_t;
using i64 = int64_t;
using u64 = uint64_t;

using i128 = __int128_t;
using u128 = __uint128_t;

template <typename T> using MaxHeap = priority_queue<T, vector<T>, less<T>>;
template <typename T> using MinHeap = priority_queue<T, vector<T>, greater<T>>;
// }}}

// hide {{{
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-const-variable"
#endif
// }}}

// 適宜調整
constexpr bool AUTOFLUSH = false;

constexpr int IOS_PREC = 12;

constexpr int INF_I32 = 1'010'000'000;
constexpr i64 INF_I64 = 1'010'000'000'000'000'000LL;

constexpr auto INF = INF_I64;
constexpr double EPS = 1e-12;

constexpr i64 MOD = 1'000'000'007;

// hide {{{
#ifdef __clang__
#pragma clang diagnostic pop
#endif
// }}}

// util {{{
constexpr i32 I32_MAX = numeric_limits<i32>::max();
constexpr i32 I32_MIN = numeric_limits<i32>::min();

constexpr i64 I64_MAX = numeric_limits<i64>::max();
constexpr i64 I64_MIN = numeric_limits<i64>::min();

constexpr double PI = 3.14159265358979323846;

template <typename F> class RecursiveFunc {
public:
  RecursiveFunc(F &&f) : f_(f) {}

  template <typename... Args> decltype(auto) operator()(Args &&...args) const {
    return f_(*this, forward<Args>(args)...);
  }

private:
  F f_;
};

template <typename F> auto RECURSIVE(F &&f) {
  return RecursiveFunc<decay_t<F>>(forward<F>(f));
}

template <typename T> int GETBIT(T x, int i) { return (x >> i) & 1; }
template <typename T> T SETBIT(T x, int i) { return x | (T(1) << i); }
template <typename T> T CLEARBIT(T x, int i) { return x & ~(T(1) << i); }

template <typename T> constexpr const T &MAX(const T &x, const T &y) {
  return std::max(x, y);
}
template <typename T, typename Comp>
constexpr const T &MAX(const T &x, const T &y, Comp comp) {
  return std::max(x, y, comp);
}
template <typename T> constexpr T MAX(initializer_list<T> ilist) {
  return std::max(ilist);
}
template <typename T, typename Comp>
constexpr T MAX(initializer_list<T> ilist, Comp comp) {
  return std::max(ilist, comp);
}

template <typename T> constexpr const T &MIN(const T &x, const T &y) {
  return std::min(x, y);
}
template <typename T, typename Comp>
constexpr const T &MIN(const T &x, const T &y, Comp comp) {
  return std::min(x, y, comp);
}
template <typename T> constexpr T MIN(initializer_list<T> ilist) {
  return std::min(ilist);
}
template <typename T, typename Comp>
constexpr T MIN(initializer_list<T> ilist, Comp comp) {
  return std::min(ilist, comp);
}

template <typename T> constexpr T ABS(T x) {
  static_assert(is_signed<T>::value, "ABS(): argument must be signed");
  return x < 0 ? -x : x;
}

template <typename T> constexpr T abs_diff(T x, T y) {
  return x < y ? y - x : x - y;
}

template <typename T> constexpr bool is_odd(T x) { return x % 2 != 0; }
template <typename T> constexpr bool is_even(T x) { return x % 2 == 0; }

template <typename T> constexpr bool parity_same(T x, T y) {
  return (is_odd(x) && is_odd(y)) || (is_even(x) && is_even(y));
}

template <typename T> constexpr int cmp(T x, T y) { return (y < x) - (x < y); }

template <typename T> constexpr int sgn(T x) { return cmp(x, T(0)); }

constexpr i64 ipow(i64 a, i64 b) {
  assert(b >= 0);
  i64 res(1);
  for (i64 i = 0; i < b; ++i)
    res *= a;
  return res;
}

pair<i64, i64> divmod(i64 a, i64 b) { return make_pair(a / b, a % b); }

constexpr i64 div_ceil(i64 a, i64 b) {
  return a / b + (((a < 0) ^ (b > 0)) && (a % b));
}

constexpr i64 div_floor(i64 a, i64 b) {
  return a / b - (((a > 0) ^ (b > 0)) && (a % b));
}

constexpr i64 modulo(i64 a, i64 b) {
  assert(0 < b);
  i64 r = a % b;
  return r >= 0 ? r : r + b;
}

template <typename T> constexpr T CLAMP(T x, T lo, T hi) {
  assert(lo <= hi);
  if (x < lo)
    return lo;
  else if (hi < x)
    return hi;
  else
    return x;
}

template <typename T, typename U> bool chmax(T &xmax, const U &x) {
  if (xmax < x) {
    xmax = x;
    return true;
  } else {
    return false;
  }
}

template <typename T, typename U> bool chmin(T &xmin, const U &x) {
  if (x < xmin) {
    xmin = x;
    return true;
  } else {
    return false;
  }
}

template <typename T> constexpr int SIZE(const T &c) {
  return static_cast<int>(c.size());
}

template <typename T, size_t N> constexpr int SIZE(const T (&)[N]) {
  return static_cast<int>(N);
}

template <typename InputIt, typename T>
int argfind(InputIt first, InputIt last, const T &x) {
  auto it = find(first, last, x);
  return distance(first, it);
}

template <typename InputIt> int argmax(InputIt first, InputIt last) {
  auto it = max_element(first, last);
  return distance(first, it);
}

template <typename InputIt> int argmin(InputIt first, InputIt last) {
  auto it = min_element(first, last);
  return distance(first, it);
}

template <typename InputIt> bool alltrue(InputIt first, InputIt last) {
  return all_of(first, last, [](bool b) { return b; });
}

template <typename InputIt> bool anytrue(InputIt first, InputIt last) {
  return any_of(first, last, [](bool b) { return b; });
}

template <typename InputIt> bool allfalse(InputIt first, InputIt last) {
  return !anytrue(first, last);
}

template <typename InputIt> bool anyfalse(InputIt first, InputIt last) {
  return !alltrue(first, last);
}

// hash {{{
template <typename T> struct myhash {
  size_t operator()(const T &x) const {
    hash<T> h;
    return h(x);
  }
};

template <typename T> size_t myhash_value(const T &x) { return hash<T>()(x); }

template <typename T> void myhash_combine(size_t &seed, const T &x) {
  seed ^= myhash_value(x) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}

template <typename T1, typename T2> struct myhash<pair<T1, T2>> {
  size_t operator()(const pair<T1, T2> &p) const {
    size_t seed = 0;
    myhash_combine(seed, p.first);
    myhash_combine(seed, p.second);
    return seed;
  }
};

template <size_t I = 0, typename... TS,
          enable_if_t<I == sizeof...(TS), nullptr_t> = nullptr>
void TUPLEHASH(size_t &, const tuple<TS...> &) {}

template <size_t I = 0, typename... TS,
          enable_if_t<I<sizeof...(TS), nullptr_t> = nullptr> void TUPLEHASH(
              size_t &seed, const tuple<TS...> &t) {
  myhash_combine(seed, get<I>(t));
  TUPLEHASH<I + 1, TS...>(seed, t);
}

template <typename... TS> struct myhash<tuple<TS...>> {
  size_t operator()(const tuple<TS...> &t) const {
    size_t seed = 0;
    TUPLEHASH(seed, t);
    return seed;
  }
};

template <typename Seq> void SEQHASH(size_t &seed, const Seq &v) {
  for (const auto &e : v)
    myhash_combine(seed, e);
}

template <typename T> struct myhash<vector<T>> {
  size_t operator()(const vector<T> &v) const {
    size_t seed = 0;
    SEQHASH(seed, v);
    return seed;
  }
};

template <typename T, size_t N> struct myhash<array<T, N>> {
  size_t operator()(const array<T, N> &v) const {
    size_t seed = 0;
    SEQHASH(seed, v);
    return seed;
  }
};

template <typename T> using HashSet = unordered_set<T, myhash<T>>;

template <typename K, typename V>
using HashMap = unordered_map<K, V, myhash<K>>;

template <typename T> using HashMultiSet = unordered_multiset<T, myhash<T>>;

template <typename K, typename V>
using HashMultiMap = unordered_multimap<K, V, myhash<K>>;
// }}}

template <typename T, typename... Args>
void vec_emplace_front(vector<T> &v, Args &&...args) {
  v.emplace(begin(v), args...);
}

template <typename K, typename V>
pair<typename map<K, V>::iterator, bool>
insert_or_assign(map<K, V> &m, const K &k, const V &v) {
  auto it = m.lower_bound(k);
  if (it != end(m) && !m.key_comp()(k, it->first)) {
    it->second = v;
    return make_pair(it, false);
  } else {
    auto it_ins = m.insert(it, make_pair(k, v));
    return make_pair(it_ins, true);
  }
}

template <typename K, typename V>
pair<typename HashMap<K, V>::iterator, bool>
insert_or_assign(HashMap<K, V> &m, const K &k, const V &v) {
  auto it = m.find(k);
  if (it != end(m)) {
    it->second = v;
    return make_pair(it, false);
  } else {
    auto it_ins = m.insert(it, make_pair(k, v));
    return make_pair(it_ins, true);
  }
}

template <typename T> string TO_STRING(const T &x) {
  ostringstream out;
  out << x;
  return out.str();
}

template <typename InputIt>
string JOIN(InputIt first, InputIt last, const string &sep) {
  ostringstream out;
  while (first != last) {
    out << *first++;
    if (first != last)
      out << sep;
  }
  return out.str();
}

template <typename InputIt> auto SUM(InputIt first, InputIt last) {
  using T = typename iterator_traits<InputIt>::value_type;
  return accumulate(first, last, T());
}

template <typename T> void UNIQ(T &c) {
  c.erase(unique(begin(c), end(c)), end(c));
}

template <typename T, typename F>
enable_if_t<rank<T>::value == 0> ARRAY_FOREACH(T &e, F f) {
  f(e);
}

template <typename Array, typename F>
enable_if_t<rank<Array>::value != 0> ARRAY_FOREACH(Array &ary, F f) {
  for (auto &e : ary)
    ARRAY_FOREACH(e, f);
}

template <typename Array, typename U>
enable_if_t<rank<Array>::value != 0> ARRAY_FILL(Array &ary, const U &v) {
  ARRAY_FOREACH(ary, [&v](auto &elem) { elem = v; });
}

template <typename T> T POP_BACK(vector<T> &que) {
  T x = que.back();
  que.pop_back();
  return x;
}

template <typename T> T POP_BACK(deque<T> &que) {
  T x = que.back();
  que.pop_back();
  return x;
}

template <typename T> T POP_FRONT(deque<T> &que) {
  T x = que.front();
  que.pop_front();
  return x;
}

template <typename T, typename C> T POP(stack<T, C> &stk) {
  T x = stk.top();
  stk.pop();
  return x;
}

template <typename T, typename C> T POP(queue<T, C> &que) {
  T x = que.front();
  que.pop();
  return x;
}

template <typename T, typename Cont, typename Cmp>
T POP(priority_queue<T, Cont, Cmp> &que) {
  T x = que.top();
  que.pop();
  return x;
}

template <typename T> void RD(T &x) {
  cin >> x;
#ifdef LOCAL
  if (!cin)
    assert(false);
#endif
}

template <typename T> void RD(vector<T> &v, int n) {
  v.reserve(n);
  for (int i = 0; i < n; ++i) {
    T e;
    RD(e);
    v.emplace_back(e);
  }
}

template <typename T, size_t N> void RD(array<T, N> &v) {
  for (size_t i = 0; i < N; ++i) {
    RD(v[i]);
  }
}

// 出力 {{{
// FPRINTSEQ {{{
template <typename InputIt>
ostream &FPRINTSEQ(ostream &out, InputIt first, InputIt last) {
  while (first != last) {
    out << *first++;
    if (first != last)
      out << ' ';
  }
  return out;
}
template <typename InputIt> ostream &PRINTSEQ(InputIt first, InputIt last) {
  return FPRINTSEQ(cout, first, last);
}
template <typename InputIt> ostream &DPRINTSEQ(InputIt first, InputIt last) {
#ifdef LOCAL
  FPRINTSEQ(cerr, first, last);
#endif
  return cerr;
}
// }}}

// 1次元生配列 {{{
template <typename T, size_t N>
ostream &FPRINTARRAY1(ostream &out, const T (&c)[N]) {
  return FPRINTSEQ(out, begin(c), end(c));
}
template <typename T, size_t N> ostream &PRINTARRAY1(const T (&c)[N]) {
  return FPRINTARRAY1(cout, c);
}
template <typename T, size_t N> ostream &DPRINTARRAY1(const T (&c)[N]) {
#ifdef LOCAL
  FPRINTARRAY1(cerr, c);
#endif
  return cerr;
}
// }}}

// 2次元生配列 {{{
template <typename T, size_t N1, size_t N2>
ostream &FPRINTARRAY2(ostream &out, const T (&c)[N1][N2]) {
  out << '\\n';
  for (const auto &e : c) {
    FPRINTARRAY1(out, e) << '\\n';
  }
  return out;
}
template <typename T, size_t N1, size_t N2>
ostream &PRINTARRAY2(const T (&c)[N1][N2]) {
  return FPRINTARRAY2(cout, c);
}
template <typename T, size_t N1, size_t N2>
ostream &DPRINTARRAY2(const T (&c)[N1][N2]) {
#ifdef LOCAL
  FPRINTARRAY2(cerr, c);
#endif
  return cerr;
}
// }}}

// 非mapコンテナ {{{
template <typename T> ostream &operator<<(ostream &out, const vector<T> &c) {
  return FPRINTSEQ(out, begin(c), end(c));
}

// 特別扱い
template <typename T>
ostream &operator<<(ostream &out, const vector<vector<T>> &c) {
  out << '\\n';
  for (const auto &e : c) {
    out << e << '\\n';
  }
  return out;
}

// 特別扱い
ostream &operator<<(ostream &out, const vector<string> &c) {
  out << '\\n';
  for (const string &e : c) {
    out << e << '\\n';
  }
  return out;
}

template <typename T> ostream &operator<<(ostream &out, const deque<T> &c) {
  return FPRINTSEQ(out, begin(c), end(c));
}

template <typename T> ostream &operator<<(ostream &out, const set<T> &c) {
  return FPRINTSEQ(out, begin(c), end(c));
}

template <typename T> ostream &operator<<(ostream &out, const HashSet<T> &c) {
  return out << set<T>(begin(c), end(c));
}

template <typename T> ostream &operator<<(ostream &out, const multiset<T> &c) {
  return FPRINTSEQ(out, begin(c), end(c));
}

template <typename T>
ostream &operator<<(ostream &out, const HashMultiSet<T> &c) {
  return out << multiset<T>(begin(c), end(c));
}

template <typename T, size_t N>
ostream &operator<<(ostream &out, const array<T, N> &c) {
  return FPRINTSEQ(out, begin(c), end(c));
}
// }}}

// mapコンテナ {{{
template <typename InputIt>
ostream &FPRINTMAP(ostream &out, InputIt first, InputIt last) {
  out << "{\\n";
  for (auto it = first; it != last; ++it) {
    out << "  " << it->first << " : " << it->second << '\\n';
  }
  out << "}\\n";
  return out;
}
template <typename InputIt> ostream &PRINTMAP(InputIt first, InputIt last) {
  return FPRINTMAP(cout, first, last);
}
template <typename InputIt> ostream &DPRINTMAP(InputIt first, InputIt last) {
#ifdef LOCAL
  FPRINTMAP(cerr, first, last);
#endif
  return cerr;
}

template <typename K, typename V>
ostream &operator<<(ostream &out, const map<K, V> &c) {
  return FPRINTMAP(out, begin(c), end(c));
}

template <typename K, typename V>
ostream &operator<<(ostream &out, const HashMap<K, V> &c) {
  return out << map<K, V>(begin(c), end(c));
}

template <typename K, typename V>
ostream &operator<<(ostream &out, const multimap<K, V> &c) {
  return FPRINTMAP(out, begin(c), end(c));
}

template <typename K, typename V>
ostream &operator<<(ostream &out, const HashMultiMap<K, V> &c) {
  return out << multimap<K, V>(begin(c), end(c));
}
// }}}

// stack/queue/priority_queue {{{
template <typename T, typename C>
ostream &operator<<(ostream &out, stack<T, C> c) {
  while (!c.empty()) {
    out << c.top();
    c.pop();
    if (!c.empty())
      out << ' ';
  }
  return out;
}

template <typename T, typename C>
ostream &operator<<(ostream &out, queue<T, C> c) {
  while (!c.empty()) {
    out << c.front();
    c.pop();
    if (!c.empty())
      out << ' ';
  }
  return out;
}

template <typename T, typename Cont, typename Cmp>
ostream &operator<<(ostream &out, priority_queue<T, Cont, Cmp> c) {
  while (!c.empty()) {
    out << c.top();
    c.pop();
    if (!c.empty())
      out << ' ';
  }
  return out;
}
// }}}

// pair/tuple {{{
template <typename T1, typename T2>
ostream &operator<<(ostream &out, const pair<T1, T2> &p) {
  return out << '(' << p.first << ',' << p.second << ')';
}

template <size_t I = 0, typename... TS,
          enable_if_t<I == sizeof...(TS), nullptr_t> = nullptr>
ostream &FPRINTTUPLE(ostream &out, const tuple<TS...> &) {
  if (sizeof...(TS) == 0)
    out << '(';
  return out << ')';
}

template <size_t I = 0, typename... TS,
          enable_if_t<I<sizeof...(TS), nullptr_t> = nullptr> ostream
              &FPRINTTUPLE(ostream &out, const tuple<TS...> &t) {
  if (I == 0)
    out << '(';
  else
    out << ',';
  out << get<I>(t);
  return FPRINTTUPLE<I + 1, TS...>(out, t);
}

template <typename... TS>
ostream &operator<<(ostream &out, const tuple<TS...> &t) {
  return FPRINTTUPLE(out, t);
}
// }}}

// PRINT {{{
ostream &FPRINT(ostream &out) { return out; }

template <typename T, typename... TS>
ostream &FPRINT(ostream &out, const T &x, const TS &...args) {
  out << x;
  if (sizeof...(args))
    out << ' ';
  return FPRINT(out, args...);
}

template <typename... TS> ostream &FPRINTLN(ostream &out, const TS &...args) {
  FPRINT(out, args...);
  return out << '\\n';
}

template <typename... TS> ostream &PRINT(const TS &...args) {
  return FPRINT(cout, args...);
}

template <typename... TS> ostream &PRINTLN(const TS &...args) {
  return FPRINTLN(cout, args...);
}

template <typename... TS> ostream &DPRINT(const TS &...args) {
#ifdef LOCAL
  FPRINT(cerr, args...);
#endif
  return cerr;
}

template <typename... TS> ostream &DPRINTLN(const TS &...args) {
#ifdef LOCAL
  FPRINTLN(cerr, args...);
#endif
  return cerr;
}
// }}}
// }}}

void FLUSH() { cout.flush(); }

[[noreturn]] void EXIT() {
#ifdef LOCAL
  cout.flush();
  cerr.flush();
#else
  FLUSH();
#endif
  // quick_exit(0); // does not work on codeforces
  _Exit(0);
}

struct IoInit {
  IoInit() {
#ifndef LOCAL
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
#endif
    cout << fixed << setprecision(IOS_PREC);

    if (AUTOFLUSH)
      cout << unitbuf;
  }
} IOINIT;

#define FOR(i, start, end) for (i64 i = (start); i < (end); ++i)
#define REP(i, n) FOR(i, 0, n)

#define ALL(f, c, ...)                                                         \\
  (([&](decltype((c)) cc) { return (f)(begin(cc), end(cc), ##__VA_ARGS__); })( \\
      c))

#define GENERIC(f)                                                             \\
  ([](auto &&...args) -> decltype(auto) {                                      \\
    return (f)(forward<decltype(args)>(args)...);                              \\
  })

#define DBG(x) DPRINTLN('L', __LINE__, ':', #x, ':', (x))

#define PAIR make_pair
#define TUPLE make_tuple
// }}}

struct Edge {
  i64 to;
  i64 cap;
  i64 flow;
  Edge(i64 t, i64 c, i64 f) : to(t), cap(c), flow(f) {}
};
ostream &operator<<(ostream &out, const Edge &e) {
  return out << '(' << e.to << ',' << e.cap << ',' << e.flow << ')';
}

i64 N;
i64 M;
vector<vector<Edge>> G;

i64 dfs() {
  deque<bool> visited(N, false);

  return RECURSIVE([&](auto &&self, i64 v, i64 t, i64 f) -> i64 {
    if (v == t)
      return f;

    visited[v] = true;

    for (auto &e : G[v]) {
      if (visited[e.to])
        continue;
      if (e.flow >= e.cap)
        continue;

      i64 fnew = MIN(f, e.cap - e.flow);
      i64 res = self(e.to, t, fnew);
      if (res > 0) {
        e.flow = res;
        return res;
      }
    }

    return 0;
  })(0, N - 1, INF);
}

void solve() {
  i64 ans = 0;
  while (true) {
    i64 f = dfs();
    DBG(G);
    if (f == 0)
      break;
    ans += f;
  }

  PRINTLN(ans);
}

signed main(signed /*argc*/, char ** /*argv*/) {
  RD(N);
  RD(M);

  G.resize(N);
  REP(_, M) {
    i64 from, to, cap;
    RD(from);
    RD(to);
    RD(cap);
    G[from].emplace_back(to, cap, 0);
  }

  DBG(G);

  solve();

  EXIT();
}