import std.algorithm;
import std.array;
import std.ascii;
import std.container;
import std.conv;
import std.math;
import std.numeric;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void log(A...)(A arg) {
    stderr.writeln(arg);
}
int size(T)(in T s) {
    return cast(int)s.length;
}

class Edge {
    int from, to, cap;
    Edge rev;
    this(int from, int to, int cap) {
        this.from = from;
        this.to = to;
        this.cap = cap;
    }
}
class Graph {
    int V; // ?¬????????¬¨??°
    Edge[][] G;
    this(int V) {
        this.V = V;
        this.G = new Edge[][V];
    }
    void addEdge(int from, int to, int cap) {
        auto e = new Edge(from ,to, cap);
        auto r = new Edge(to, from, 0);
        e.rev = r; r.rev = e;
        G[from] ~= e; G[to] ~= r;
    }
    int maxFlow(int s, int t) {
        auto used = new bool[V];
        int dfs(int v, int t, int f) {
            if (v == t) return f;
            used[v] = true;
            foreach (e; G[v]) {
                if (!used[e.to] && e.cap > 0) {
                    int d = dfs(e.to, t, min(f, e.cap));
                    if (d > 0) {
                        e.cap -= d;
                        e.rev.cap += d;
                        return d;
                    }
                }
            }
            return 0;
        }
        int flow = 0;
        while (true) {
            used[0 .. $] = false;
            int f = dfs(s, t, cast(int)1e9);
            if (f == 0) return flow;
            flow += f;
        }
    }
}

void main() {
    int V, E; readf("%d %d\n", &V, &E);
    auto g = new Graph(V);
    foreach (_; 0 .. E) {
        int s, t, c; readf("%d %d %d\n", &s, &t, &c);
        g.addEdge(s, t, c);
    }
    writeln(g.maxFlow(0, V - 1));
}