#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 100005;
const int maxm = 2000005;
const int inf = 0x3f3f3f3f;
struct DINIC
{
struct node
{
int u,v,w,next;
}edge[maxm];
int deep[maxn],dl[maxm],fir[maxm];
int cnt,aim;
void init()
{
memset(fir,-1,sizeof fir);
cnt=0;
}
void add(int u,int v,int w)
{
edge[cnt].u=u,edge[cnt].v=v,edge[cnt].w=w;
edge[cnt].next=fir[u];fir[u]=cnt++;
edge[cnt].u=v,edge[cnt].v=u,edge[cnt].w=0;
edge[cnt].next=fir[v];fir[v]=cnt++;
}
bool bfs(int S,int T)
{
memset(deep, 0, sizeof deep);
deep[S] = 1;dl[1] = S;
int head = 0, tail = 1;
while(head != tail){
int v = dl[++head];
for(int u = fir[v]; ~u; u = edge[u].next){
if(edge[u].w && !deep[edge[u].v]){
deep[edge[u].v] = deep[v]+1;
dl[++tail] = edge[u].v;
}
}
}
return deep[T];
}
int dfs(int now, int fl)
{
if(now == aim) return fl;
int f = 0;
for(int u = fir[now]; ~u && fl; u = edge[u].next){
if(edge[u].w && deep[edge[u].v] == deep[now]+1){
int x = dfs(edge[u].v, min(fl,edge[u].w));
edge[u].w -= x;
edge[u^1].w += x;
fl -= x;
f += x;
}
}
if(!f) deep[now] = -2;
return f;
}
int maxflow(int S,int T)
{
aim = T;
int ans = 0;
while(bfs(S, T)) ans += dfs(S, inf);
return ans;
}
}dinic;
int main()
{
//n个点,m条边,求S到T的最大流/最小割(dinic算法)
int n,m;
while(~scanf("%d%d",&n,&m)){
int S,T;
scanf("%d%d",&S,&T);
dinic.init();
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
dinic.add(u,v,w);
}
printf("%d\n",dinic.maxflow(S,T));
}
return 0;
}