#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int NMAX = 1010;
struct Edge {
int to, flow, next;
};
namespace Flow {
vector <Edge> edges;
vector <int> head, act, h;
int S, D;
int cmax;
void add_edge(int from, int to, int flow) {
cmax = max(cmax, flow);
edges.push_back({ to, flow, edges.size() });
swap(edges.back().next, head[from]);
edges.push_back({ from, 0, edges.size() });
swap(edges.back().next, head[to]);
}
bool bfs() {
fill(h.begin(), h.end(), 0);
h[S] = 1;
vector <int> q = { S };
for (int i = 0; i < q.size(); i++) {
int nod = q[i];
if (nod == D)
continue;
for (int vec = head[nod]; vec != -1; vec = edges[vec].next)
if (edges[vec].flow >= cmax && !h[edges[vec].to])
h[edges[vec].to] = 1 + h[nod], q.push_back(edges[vec].to);
}
return h[D];
}
int dfs(int nod, int fmax) {
if (!fmax || nod == D)
return fmax;
int ans = 0;
while (fmax && act[nod] != -1) {
auto & vec = edges[act[nod]];
int d = 0;
if (vec.flow >= cmax && h[vec.to] == 1 + h[nod])
d = dfs(vec.to, min(fmax, vec.flow));
fmax -= d, ans += d;
vec.flow -= d, edges[act[nod] ^ 1].flow += d;
if (fmax || !d)
act[nod] = edges[act[nod]].next;
}
return ans;
}
int flow() {
int ans = 0;
while (cmax) {
while (bfs()) {
act = head;
ans += dfs(S, 1e9);
}
cmax /= 2;
}
return ans;
}
void init(int N, int s, int d) {
head = vector <int> (N + 1, -1);
S = s, D = d;
h = vector <int> (N + 1, 0);
}
}
int main()
{
FILE *in = fopen("maxflow.in", "r");
int n, m, a, b, c;
fscanf(in, "%d%d", &n, &m);
Flow::init(n, 1, n);
while (m--) {
fscanf(in, "%d%d%d", &a, &b, &c);
Flow::add_edge(a, b, c);
}
FILE *out = fopen("maxflow.out", "w");
fprintf(out, "%d\n", Flow::flow());
return 0;
}