RT
#include<bits/stdc++.h>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
const ll MAXN=3e4+5,MAXM=3e4+5;
ll n,m,s,t,x,y,z;
struct MF{
struct edge{
ll u,v,w,nxt,flow;
}e[MAXM];
ll head[MAXN],edge_num;
ll max_flow;
ll deep[MAXN],cur[MAXN];
void init(){
memset(head,0,sizeof(head));
edge_num=1;
return;
}
void add_edge(ll From,ll To,ll Len){
edge_num++;
e[edge_num]=(edge){From,To,Len,head[From],0};
head[From]=edge_num;
edge_num++;
e[edge_num]=(edge){To,From,-Len,head[To],0};
head[To]=edge_num;
return;
}
bool bfs(){
// cout<<"!!!!!!!!!!\n";
queue<ll> q;
memset(deep,0,sizeof(deep));
deep[s]=1;
q.push(s);
while(q.size()){
ll now=q.front();
q.pop();
for(ll i=head[now];i;i=e[i].nxt){
if(!deep[e[i].v]&&e[i].w>e[i].flow){
deep[e[i].v]=deep[now]+1;
q.push(e[i].v);
}
}
// cout<<"!\n";
}
return deep[t];
}
ll dfs(ll now,ll flow_l){
if(now==t||flow_l==0)return flow_l;
ll now_flow=0,d;
for(ll &i=cur[now];i;i=e[i].nxt){
if(deep[e[i].v]==deep[now]+1&&(d=dfs(e[i].v,min(flow_l-now_flow,e[i].w-e[i].flow)))){
now_flow+=d;
e[i].flow+=d;
e[i^1].flow-=d;
if(now_flow==flow_l)return now_flow;
}
}
return now_flow;
}
void dinic(){
while(bfs()){
// cout<<"?\n";
memcpy(cur,head,sizeof(head));
max_flow+=dfs(s,1e18);
}
return;
}
}mf;
int main(){
cin>>n>>m>>s>>t;
mf.init();
for(int i=1;i<=m;i++){
cin>>x>>y>>z;
mf.add_edge(x,y,z);
}
// cout<<"?????????????????\n";
mf.dinic();
cout<<mf.max_flow;
return 0;
}