/**
* author: Akvicor
* created: 2019-07-26 18-37-11
**/
#include <bits/stdc++.h>
using namespace std;
#ifdef DEBUG
#define FAST_IO 17
#else
#define FAST_IO //ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define endl '\n'
#endif
#define rep(i, n) for(int i = 0; i < (n); ++i)
#define reep(i, n) for(int i = 0; i <= (n); ++i)
#define lop(i, a, n) for(int i = a; i < (n); ++i)
#define loop(i, a, n) for(int i = a; i <= (n); ++i)
#define per(i, a, n) for(int i = a; i >= n; --i)
#define prec(x) fixed << setprecision(x)
#define ms(s, n) memset(s, n, sizeof(s))
#define mod(x) ((x) %= MOD)
#define all(v) (v).begin(), (v).end()
#define sz(x) ((int)(x).size())
#define mp(x, y) make_pair(x, y)
#define pb(x) push_back(x)
#define fi first
#define se second
#define MOD(x) const int MOD = (int)x
#define MAXN(x) const int MAXN = (int)x + 10
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef vector<PII> VII;
typedef pair<LL, LL> PLL;
typedef vector<LL> VL;
typedef vector<PLL> VLL;
namespace SOL {
const double EPS = 1e-6;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const LL LINF = 0x7f7f7f7f7f7f7f7f;
/** >------- Akvicor's Solution -------< **/
MOD(1e9 + 7);
MAXN(5e3);
struct Dinic {
Dinic(int n) {
G = vector<vector<int> >(n + 10);
d = vector<int>(n + 10);
vis = vector<bool>(n + 10);
cur = vector<int>(n + 10);
}
struct Edge {
int from, to, cap, flow;
};
int s, t; //节点数,边数,源点编号,汇点编号
vector<Edge> edges; //边表,edges[e]和edges[e^1]互为反向弧
vector<vector<int> > G; //邻接表,G[i][j]表示节点i的第j条边在e中的序号
vector<bool> vis; //bfs用
vector<int> d; //从起点到i的距离
vector<int> cur; //当前弧下标
void add_edge(int from, int to, int cap) {
edges.push_back({from, to, cap, 0});
edges.push_back({to, from, 0, 0});
G[from].push_back(edges.size() - 2);
G[to].push_back(edges.size() - 1);
}
bool BFS() {
fill(vis.begin(), vis.end(), false);
queue<int> q;
q.push(s);
d[s] = 0;
vis[s] = true;
while (!q.empty()) {
for (int id : G[q.front()]) {
Edge &e = edges[id];
if (!vis[e.to] && e.cap > e.flow) {
vis[e.to] = true;
d[e.to] = d[q.front()] + 1;
q.push(e.to);
}
}
q.pop();
}
return vis[t];
}
long long DFS(int u, int a) {
if (u == t || a == 0) return a;
int flow = 0, f;
for (int &i = cur[u]; i < (int) G[u].size(); ++i) {
Edge &e = edges[G[u][i]];
if (d[u] + 1 == d[e.to] &&
(f = DFS(e.to, min(a, e.cap - e.flow))) > 0) {
e.flow += f;
edges[G[u][i] ^ 1].flow -= f;
flow += f;
a -= f;
if (a == 0) break;
}
}
return flow;
}
long long run(int _s, int _t) {
s = _s;
t = _t;
long long flow = 0;
while (BFS()) {
fill(cur.begin(), cur.end(), 0);
flow += DFS(s, 0x3f3f3f3f);
}
return flow;
}
};
void solve() {
FAST_IO;
int n, m, s, t, u, v, w;
cin >> n >> m >> s >> t;
struct Dinic di = Dinic(n);
for (int i = 0; i < m; ++i) {
cin >> u >> v >> w;
di.add_edge(u, v, w);
}
cout << di.run(s, t) << endl;
}
/** >----------------------------------< **/
}
int main() {
#ifdef DEBUG
int DEBUGCNT = 0;
clock_t DEBUGstart, DEBUGfinish;
double DEBUGduration;
cout << endl << ">------- Akvicor's Solution -------<" << endl << endl;
while (DEBUGCNT < 70) {
cout << ">---> Test: #" << DEBUGCNT << " <---<" << endl;
DEBUGstart = clock();
#endif
SOL::solve();
#ifdef DEBUG
DEBUGfinish = clock();
DEBUGduration = (double)(DEBUGfinish - DEBUGstart)*1000 / CLOCKS_PER_SEC;
cout << ">---> Test: #" << DEBUGCNT << " time: " << fixed << setprecision(4) << DEBUGduration << " ms <---<" << endl << endl;
if (cin.eof()) break;
if (!cin.good()) break;
if (cin.fail()) break;
if (cin.bad()) break;
++DEBUGCNT;
}
cout << ">----------------------------------<" << endl << endl;
#endif
return 0;
}