#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = a; i < (b); i++)
#define Rep(i, a, b) for (int i = a; i >= (b); i--)
#define pb push_back
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define fi first
#define se second
#define SZ(x) (int)(x.size())
#define lowbit(x) ((x) & -(x))
using db = double;
using ll = long long;
using ull = unsigned long long;
using vi = vector<int>;
using vvi = vector<vi>;
using pii = pair<int, int>;
using i128 = __int128_t;
// Think twice, code once
namespace Dinic {
const int N = ;
const int inf = ;
struct Edge {
int from, to, cap, flow;
};
bool operator<(const Edge &a, const Edge &b) {
return a.from < b.from || (a.from == b.from && a.to < b.to);
}
int n, m, s, t;
vector<Edge> edges; // 边数的两倍
vector<int> G[N]; // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
bool vis[N]; // BFS使用
int d[N]; // 从起点到i的距离
int cur[N]; // 当前弧指针
void init(int _n) {
n = n;
for (int i = 0; i < n; i++) G[i].clear();
edges.clear();
}
void add(int from, int to, int cap) {
edges.push_back((Edge){from, to, cap, 0});
edges.push_back((Edge){to, from, 0, 0});
m = edges.size();
G[from].push_back(m - 2);
G[to].push_back(m - 1);
}
bool BFS() { // 最后一次bfs走过的都是交错路径,可用于二分图博弈判断H点是否必须
memset(vis, 0, sizeof(int) * n);
queue<int> Q;
Q.push(s);
vis[s] = 1;
d[s] = 0;
while (!Q.empty()) {
int x = Q.front();
Q.pop();
for (int i = 0; i < G[x].size(); i++) {
Edge &e = edges[G[x][i]];
if (!vis[e.to] && e.cap > e.flow) {
vis[e.to] = 1;
d[e.to] = d[x] + 1;
Q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int x, int a) {
if (x == t || a == 0) return a;
int flow = 0, f;
for (int &i = cur[x]; i < G[x].size(); i++) {
Edge &e = edges[G[x][i]];
if (d[x] + 1 == d[e.to] &&
(f = DFS(e.to, min(a, e.cap - e.flow))) > 0) {
e.flow += f;
edges[G[x][i] ^ 1].flow -= f;
flow += f;
a -= f;
if (a == 0) break;
}
}
return flow;
}
int Maxflow(int _s, int _t) {
s = _s, t = _t;
int flow = 0;
while (BFS()) {
memset(cur, 0, sizeof(int) * n);
flow += DFS(s, inf);
}
return flow;
}
} // namespace Dinic
void solve() {
int n, m, s, t; cin >> n >> m >> s >> t; s--, t--;
Dinic::init(n);
while (m--) {
int u, v, c; cin >> u >> v >> c; u--, v--;
Dinic::add(u, v, c);
}
cout << Dinic::Maxflow(s, t) << endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1;
// cin >> T;
while (T--) solve();
return 0;
}