#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
using namespace std;
ifstream in("maxflow.in");
ofstream out("maxflow.out");
int const INF = 1e9+7;
struct Edge{
int to;
int flow;
};
int const NMAX = 1000;
int dist[1 + NMAX];
vector <Edge> edges;
vector <int> g[1 + NMAX];
int edge_ind[1 + NMAX];
void addEdge(int from, int to, int flow) {
edges.push_back({to, flow});
edges.push_back({from, 0});
g[from].push_back(edges.size()-2);
g[to].push_back(edges.size()-1);
}
void BFS(int start, int n) {
for(int i = 1;i <= n;i++) {
dist[i] = INF;
edge_ind[i] = 0;
}
queue <int> q;
q.push(start);
dist[start] = 0;
while(!q.empty()) {
int from = q.front();
q.pop();
for(int i = 0;i < g[from].size();i++) {
int to = edges[g[from][i]].to, flow = edges[g[from][i]].flow;
if(flow > 0 && dist[from] + 1 < dist[to]) {
dist[to] = dist[from] + 1;
q.push(to);
}
}
}
}
void pushEdge(int ind, int flow) {
edges[ind].flow -= flow;
edges[ind^1].flow += flow;
}
int computePushed(int node, int minflow, int sink) {
if(node == sink) {
return minflow;
} else {
int pushed = 0;
for(int i = edge_ind[node];i < g[node].size();i++) {
int to = edges[g[node][i]].to, flow = edges[g[node][i]].flow;
if(flow > 0 && dist[node] + 1 <= dist[to] && dist[to] != INF) {
int tempPush = computePushed(to, min(minflow - pushed, flow), sink);
pushed += tempPush;
pushEdge(g[node][i], tempPush);
if(pushed == minflow) {
return pushed;
}
}
edge_ind[node]++;
}
return pushed;
}
}
int computeDinic(int source, int sink, int n) {
int ans = 0;
bool canPush = true;
while(canPush) {
BFS(source, n);
canPush = false;
int pushed = computePushed(source, INF, sink);
ans += pushed;
if(pushed > 0) {
canPush = true;
}
}
return ans;
}
int main() {
int n, m;
in >> n >> m;
for(int i = 1;i <= m;i++) {
int a, b, c;
in >> a >> b >> c;
addEdge(a, b, c);
}
out << computeDinic(1, n, n);
return 0;
}