#include <bits/stdc++.h>

#ifndef LOCAL_
#define fprintf if( false ) fprintf
#endif // LOCAL_
#define dump() fprintf(stderr, "#%s.%d\n", __func__, __LINE__);
#define dumpl(x1) fprintf(stderr, "#%s.%d (%s) = (%ld)\n", __func__, __LINE__, #x1, x1);
#define dumpll(x1, x2) fprintf(stderr, "#%s.%d (%s, %s) = (%ld, %ld)\n", __func__, __LINE__, #x1, #x2, x1, x2);
#define dumplll(x1, x2, x3) fprintf(stderr, "#%s.%d (%s, %s, %s) = (%ld, %ld, %ld)\n", __func__, __LINE__, #x1, #x2, #x3, x1, x2, x3);
#define dumpd(x1) fprintf(stderr, "#%s.%d (%s) = (%lf)\n", __func__, __LINE__, #x1, x1);
#define dumpdd(x1, x2) fprintf(stderr, "#%s.%d (%s, %s) = (%lf, %lf)\n", __func__, __LINE__, #x1, #x2, x1, x2);
#define loop for(;;)
typedef int64_t Int;
typedef std::vector<Int> LI;
const double pi = 3.14159265358979323846264338;
const Int mod = 1000000007;

template<typename T> void scan1(T& x) { fprintf(stderr, "unknown type\n"); }
template<> void scan1(Int& x) { if( scanf("%" PRId64, &x) < 0 ) exit(0); }
template<> void scan1(std::string& x) { if( not ( std::cin >> x ) ) exit(0); }
template<> void scan1(LI& xs) { for(Int &x : xs) scan1(x); }
void scan() {}
template<typename Head, typename... Tail>
void scan(Head& x, Tail&... xs) {
  scan1(x); scan(xs...);
}

template<typename T>
struct Maybe {
   T x;
   bool valid;
   Maybe() : valid(false) {}
   Maybe(T x_) : x(x_), valid(true) {}
   operator T() const {
      assert( valid );
      return x;
   }
};

namespace S1 {
   struct Edge {
      Int s, d, f, c, rev;
   };
   struct Graph {
      Int n;
      std::vector<std::vector<Edge>> es;
      Graph(Int n_) : n(n_+1), es(n) {}
      void addEdge(Int s, Int d, Int c) {
         Int i = es[s].size();
         Int k = es[d].size();
         es[s].push_back({s, d, 0, c, k});
         es[d].push_back({d, s, 0, 0, i});
      }
   };
   static Int solve(Graph& graph, Int s, Int t) {
      Int res = 0;
      for(;;) {
         std::queue<Int> q; q.push(s);
         Edge dummy = {-1,-1,-1,-1,-1};
         std::vector<Edge*> prev(graph.n, &dummy);
         while( not q.empty() ) {
            Int v = q.front(); q.pop();
            for(Edge& e : graph.es[v]) {
               if( prev[e.d]->s == -1 and e.c - e.f > 0 ) {
                  q.push(e.d);
                  prev[e.d] = &e;
               }
            }
         }
         if( prev[t]->s == -1 ) break;
         Int f = (1LL << 53);
         {
            Int v = t;
            while( v != s ) {
               f = std::min(f, prev[v]->c - prev[v]->f);
               v = prev[v]->s;
            }
         }
         {
            Int v = t;
            while( v != s ) {
               prev[v]->f += f;
               graph.es[prev[v]->d][prev[v]->rev].f -= f;
               v = prev[v]->s;
            }
         }
         res += f;
         dumpl(f);
         if( f == 0 ) break;
      }
      return res;
   }
};

struct Solver {
   Solver() { fprintf(stderr, "--------Solver begin--------\n"); }
   ~Solver() { fprintf(stderr, "--------Solver end--------\n"); }
   // void solve() {
   //    Int n; scan(n);
   //    std::vector<Int> xs(n); scan(xs);
   //    S1::Graph graph(120);
   //    Int s = 110, t = 111;
   //    for(Int i = 1; i <= n; ++i) {
   //       if( xs[i-1] < 0 ) graph.addEdge(s, i, -xs[i-1]);
   //       if( xs[i-1] > 0 ) graph.addEdge(i, t, xs[i-1]);
   //       for(Int k = 2*i; k <= n; k+=i) {
   //          graph.addEdge(i, k, (1LL << 40));
   //       }
   //    }
   //    Int res = S1::solve(graph, s, t);
   //    printf("%ld\n", res);
   // }
   void solve() {
      Int n, m; scan(n, m);
      S1::Graph graph(n);
      for(Int i = 0; i < m; ++i) {
         Int a, b, c; scan(a, b, c);
         graph.addEdge(a, b, c);
      }
      Int res = S1::solve(graph, 0, n-1);
      printf("%ld\n", res);
   }
};

int main() {
   loop std::unique_ptr<Solver>(new Solver())->solve();
}

Measured memory_bytes: 3320