#include <iostream>
#include <fstream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <climits>
using namespace std;
ifstream in("maxflow.in");
ofstream out("maxflow.out");
struct Edge {
int to, flow, cap, rev;
};
int source, destination;
void addEdge(int i, int j, const vector< vector<int> > &v, vector< vector<Edge> > &g) {
g[i].push_back({j, 0, v[i][j], g[j].size()});
g[j].push_back({i, 0, v[j][i], g[i].size() - 1});
}
bool bfs(int n, vector<int> &dist, vector< vector<Edge> > &g) {
for(int i = 1; i <= n; i ++)
dist[i] = -1;
dist[source] = 0;
queue<int> q;
q.push(source);
while(q.size()) {
auto from = q.front();
q.pop();
for(auto &it : g[from])
if(it.flow < it.cap && dist[it.to] == -1) {
dist[it.to] = dist[from] + 1;
q.push(it.to);
}
}
return (dist[destination] != -1);
}
int dfs(int node, int deltaflow, const vector<int> &dist, vector<int> &rem, vector< vector<Edge> > &g) {
if(node == destination)
return deltaflow;
for(int i = rem[node]; i < g[node].size(); i ++) {
Edge &e = g[node][i];
if(dist[e.to] == (1 + dist[node])) {
int addflow = dfs(e.to, min(deltaflow, e.cap - e.flow), dist, rem, g);
if(addflow > 0) {
e.flow += addflow;
Edge &rev = g[e.to][e.rev];
rev.flow -= addflow;
rem[node] = i;
return addflow;
}
}
}
return 0;
}
int dinic(int n, vector< vector<Edge> > &g) {
int ans = 0;
vector<int> dist(n + 1, -1);
while(bfs(n, dist, g)) {
vector<int> rem(n + 1, 0);
int aux = dfs(source, INT_MAX, dist, rem, g);
while(aux) {
ans += aux;
aux = dfs(source, INT_MAX, dist, rem, g);
}
}
return ans;
}
int main() {
int n, m;
in >> n >> m;
vector< vector<Edge> > g(n + 1);
vector< vector<int> > capacity(n + 1, vector<int> (n + 1, 0));
for(int i = 1; i <= m; i ++) {
int x, y, c;
in >> x >> y >> c;
capacity[x][y] = c;
}
for(int i = 1; i <= n; i ++)
for(int j = i + 1; j <= n; j ++)
if(capacity[i][j] || capacity[j][i])
addEdge(i, j, capacity, g);
source = 1;
destination = n;
out << dinic(n, g);
return 0;
}