#include <iostream>
#include <vector>
#include <queue>
#include <utility>
#include <algorithm>
#include <numeric>
#include <cassert>

using namespace std;

const int kNil = -1;

enum class Color {
  kWhite,
  kGrey,
  kBlack,
};

template <class T>
struct Edge {
  using w_type = T;
  Edge(int u, int v, w_type w): u(u), v(v), w(w) { }
  int u, v;
  w_type w;
  bool operator<(const Edge<T> & rhs) const {
    if (w != rhs.w) { return w < rhs.w; }
    if (u != rhs.u) { return u < rhs.u; }
    return v < rhs.v;
  }
};

template <class Edge>
vector<int> BFS(const vector<Edge> & edges,
              typename vector<Edge>::size_type node_num,
              typename vector<Edge>::size_type root) {
  using size_type = typename vector<Edge>::size_type;

  vector<vector<Edge>> adjacency_list(node_num, vector<Edge>());
  for (const auto & e: edges) {
    adjacency_list[e.u].push_back(e);
  }

  queue<size_type> que;
  vector<size_type> d(node_num, numeric_limits<size_type>::max());
  vector<Color> color(node_num, Color::kWhite);
  vector<int> parent(node_num, kNil);

  d[root] = 0;
  color[root] = Color::kGrey;
  que.push(root);
  while (!que.empty()) {
    auto u = que.front();
    que.pop();
    for (const auto & e: adjacency_list[u]) {
      if (color[e.v] == Color::kWhite) {
        color[e.v] = Color::kGrey;
        d[e.v] = d[e.u] + 1;
        parent[e.v] = e.u;
        que.push(e.v);
      }
    }
    color[u] = Color::kBlack;
  }

  return parent;
}

template <class E>
decltype(auto) EdmondsKarp(vector<E> & edges,
                 typename vector<E>::size_type node_num,
                 typename vector<E>::size_type source,
                 typename vector<E>::size_type target) {
  using size_type = typename vector<E>::size_type;
  using w_type = typename E::w_type;

  const w_type kInf = numeric_limits<w_type>::max();

  vector<vector<w_type>> flow(node_num, vector<w_type>(node_num));

  while (1) {
    vector<Edge<w_type>> residual_net;
    for (const auto & e: edges) {
      auto residual_capacity = e.w - flow[e.u][e.v];
      if (residual_capacity != 0) {
        residual_net.emplace_back(e.u, e.v, residual_capacity);
      }
      if (flow[e.u][e.v] != 0) {
        residual_net.emplace_back(e.v, e.u, flow[e.u][e.v]);
      }
    }
    vector<vector<w_type>> residual_matrix(node_num, vector<w_type>(node_num, kInf));
    for (const auto & e: residual_net) {
      residual_matrix[e.u][e.v] = e.w;
    }
    for (unsigned i = 0; i < node_num; ++i) {
      residual_matrix[i][i] = 0;
    }

    auto min_capacity = kInf;
    vector<pair<size_type, size_type>> path;
    auto parents = BFS(residual_net, node_num, source);
    if (parents[target] == kNil) { break; }
    unsigned u = target;
    while (u != source) {
      unsigned pa = parents[u];
      path.emplace_back(pa, u);
      assert(residual_matrix[pa][u] != kInf);
      min_capacity = min(min_capacity, residual_matrix[pa][u]);
      u = pa;
    }
    for (const auto & e: path) {
      flow[e.first][e.second] += min_capacity;
      flow[e.second][e.first] = -flow[e.first][e.second];
    }
  }

  return accumulate(flow[source].begin(), flow[source].end(), 0);
}

int main(int argc, char const *argv[]) {
  using w_type = int;

  const w_type kInf = numeric_limits<w_type>::max();

  vector<Edge<w_type>> edges;
  unsigned V, E;
  cin >> V >> E;
  for (unsigned i = 0; i < E; ++i) {
    unsigned u, v;
    w_type c;
    cin >> u >> v >> c;
    edges.emplace_back(u, v, c);
  }
  cout << EdmondsKarp(edges, V, 0, V - 1) << endl;
  return 0;
}

Measured memory_bytes: 3260