#include <bits/stdc++.h>
#define debug(x) cout <<"DEBUG"<<" "<< #x << ":" << x << '\n'
#define rep(i,n) for(int_fast32_t i = 0; i < ((int_fast32_t)(n)); i++)   // 0-indexed up
#define rep1(i,n) for(int_fast32_t i = 1; i <= ((int_fast32_t)(n)); i++) // 1-indexed up
#define all(x) (x).begin(),(x).end()

/* GRAPH_TEMPLATE */
template<typename T>
struct Edge {
    int_fast32_t to;  // 辺の行き先
    T cost;  // 辺の重み
    Edge(int_fast32_t t, T w): to(t), cost(w) {}
};

template<typename T = int_fast32_t>
using W_Graph = std::vector<std::vector<Edge<T>>>;  // 重み付きグラフ
using Graph = std::vector<std::vector<int_fast32_t>>;  // 通常グラフ
template<typename T = int_fast32_t>
using Matrix = std::vector<std::vector<T>>;  // 隣接行列(使わなさそう...)


/* Dinic */
template<typename T>
class Dinic {
    using i32 = int_fast32_t;
private:
    std::vector<std::vector<Edge<T>>> Graph;
    std::vector<i32> level;
    std::vector<i32> iter;

    void bfs(i32 start_vertex) {
        level.assign(Graph.size(), -1);
        std::queue<T> que;
        level[start_vertex] = 0;
        que.push(start_vertex);
        while(que.size()) {
            i32 v = que.front(); que.pop();
            for(Edge<T>& e : Graph[v]) {
                T capacity = e.cost;
                if(capacity > 0 && level[e.to] == -1) {
                    level[e.to] = level[v] + 1;
                    que.push(e.to);
                }
            }
        }
    }

    T dfs(i32 v, i32 end_vertex, T flow) {
        if(v == end_vertex) return flow;
        for(auto e = (Graph[v].begin() + iter[v]); e != Graph[v].end(); ++e, ++iter[v]) {
            T& capacity = e->cost;
            if(capacity > 0 && level[v] < level[e->to]) {
                T d = dfs(e->to, end_vertex, std::min<T>(capacity, flow));
                if(d > 0) {
                    capacity -= d;
                    Graph[e->to].emplace_back(v, d);
                    return d;
                }
            }
        }
        return 0;
    }

public:
    explicit Dinic(const std::vector<std::vector<Edge<T>>>& graph)
        : Graph(graph), level(graph.size(), -1), iter(graph.size()) {}

    T execute(i32 start_vertex, i32 end_vertex) {
        T max_flow = 0;
        while(true) {
            bfs(start_vertex);
            if(level[end_vertex] == -1) return max_flow;
            iter.assign(Graph.size(), 0);
            T flow;
            while(true) {
                flow = dfs(start_vertex, end_vertex, std::numeric_limits<T>::max());
                if(flow == 0) break;
                max_flow += flow;
            }
        }
    }

};


/* Test */
using namespace std;

template<typename T>
using vec = vector<T>;
using i32 = int_fast32_t; using i64 = int_fast64_t;
using u32 = uint_fast32_t; using u64 = uint_fast64_t;
using ll = long long; using ld = long double;
using vi = vec<int_fast32_t>;
using vl = vec<int_fast64_t>;
using vii = vec<vi>;
using PII = pair<int_fast32_t, int_fast32_t>;
template<class T>
using maxheap = std::priority_queue<T>;
template<class T>
using minheap = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template<class T,class U> inline bool chmax(T &a, const U &b){if(a<b){a=b;return 1;}return 0;}
template<class T,class U> inline bool chmin(T &a, const U &b){if(a>b){a=b;return 1;}return 0;}
constexpr ll infll = (1LL<<62)-1;
constexpr int inf = (1<<30)-1;

signed main(){
    double START_TIME = clock();
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
//    cout << fixed << setprecision(15);

    i32 V, E; cin >> V >> E;
    W_Graph<i32> graph(V);

    rep(i, E) {
        i32 u,v,w; cin >> u >> v >> w;
        graph[u].emplace_back(v, w);
    }

    Dinic<i32> dnc(graph);

    cout << dnc.execute(0, V-1) << '\n';

//    printf("ElapsedTime: %5.3f ms\n",1000*((clock()-START_TIME)/CLOCKS_PER_SEC));
}




Measured memory_bytes: 3256