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

// Template Headers {{{
using pii = pair<int, int>; using vpii = vector<pii>;
using vi = vector<int>; using vvi = vector<vi>;
using ll = long long; using vll = vector<long long>;
template <class T> istream &operator>>(istream &, vector<T> &);
template <class T> ostream &operator<<(ostream &, const vector<T> &);
template <class T, class U> istream &operator>>(istream &, pair<T, U> &);
template <class T, class U> ostream &operator<<(ostream &, const pair<T, U> &);
constexpr int INF = 0x3f3f3f3f; constexpr ll BINF = 0x3f3f3f3f3f3f3f3fLL;
// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
// }}}

class MaxFlow {
    private:
        int n, s, t;
        
        struct Edge {
            int from, to;
            int cap;
        };
        
        vector<Edge> ge;
        vector<vector<int>> g;
        
        vector<int> dist;
        vector<int> par;
        
        int bfs() {
            dist.assign(n, INF);
            par.assign(n, -1);
            
            queue<int> q;
            dist[s] = 0; q.push(s);
            while (!q.empty()) {
                int u = q.front(); q.pop();
                for (int ei : g[u]) {
                    Edge &e = ge[ei];
                    if (e.cap <= 0) continue;
                    int &v = e.to;
                    if (dist[v] == INF) {
                        dist[v] = dist[u] + 1;
                        par[v] = ei;
                        q.push(v);
                    }
                }
            }
            return dist[t];
        }
                
        int augmentFlow() {
            int curFlow = INF;
            for (int u = t; par[u] != -1; u = ge[par[u]].from) curFlow = min(curFlow, ge[par[u]].cap);
            for (int u = t; par[u] != -1; u = ge[par[u]].from) {
                ge[par[u]].cap -= curFlow;
                ge[par[u] ^ 1].cap += curFlow;
            }
            return curFlow;
        }
        
    public:
        MaxFlow(int n, int s, int t) : n(n), s(s), t(t), g(n) {}
        void addEdge(int u, int v, int c) {
            Edge go = {u, v, c};
            Edge bye = {v, u, 0};
            g[u].push_back(ge.size());
            g[v].push_back(ge.size() + 1);
            ge.push_back(go);
            ge.push_back(bye);
        }

        int getMaxFlow() {
            int flowValue = 0;
            while (bfs() != INF) {
                flowValue += augmentFlow();
            }
            return flowValue;
        }
    
};

int solve() {
    int n, m; cin >> n >> m;
    MaxFlow mf(n, 0, n - 1);
    while (m--) {
        int u, v, c; cin >> u >> v >> c;
        mf.addEdge(u, v, c);
    }
    cout << mf.getMaxFlow() << endl;
	return 0;
}

// Template Main {{{
int main() {
	ios::sync_with_stdio(0);
	// precompute();
	// int t; cin >> t; for (int i=1;i<=t;i++)
	solve();
	// cout << (solve() ? "YES" : "NO") << endl;
	return 0;
}

template <class T> istream &operator>>(istream &is, vector<T> &v) {
	for (auto it=v.begin();it!=v.end();++it) is >> *it;
	return is;
}

template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
	for (auto it=v.begin();it!=v.end();) os << *it, os << " \n"[++it==v.end()];
	return os;
}

template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) {
	return is >> p.first >> p.second;
}

template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) {
	return os << p.first << ' ' << p.second;
}
// }}}

// vim: fdm=marker


Measured memory_bytes: 3204