#include <iostream>
#include <queue>
#include <cstring>
typedef long long ll;
int n;
const int maxn=5e3+10;
struct node{
int next,to,val;
}edge[maxn<<1];
int cnt=1,head[maxn<<1];
inline int min(int a,int b){ return a>b?b:a; }
void add(int from,int to,int val){
edge[++cnt].to=to;
edge[cnt].val=val;
edge[cnt].next=head[from];
head[from]=cnt;
}
int cur[maxn<<1],dep[maxn<<1];
int bfs(int s,int t){
for(int i=1;i<=n;i++){ cur[i]=head[i]; }
std::queue<int>q;q.push(s);
memset(dep,-1,sizeof dep);
dep[s]=0;
while(!q.empty()){
int temp=q.front();q.pop();
for(int i=head[temp];i;i=edge[i].next){
if(dep[edge[i].to]==-1&&edge[i].val){
dep[edge[i].to]=dep[temp]+1;
q.push(edge[i].to);
}
}
}
return dep[t];
}
ll dfs(int s,int t,int limit){
if(s==t||!limit)return limit;
ll ans=0;int f;
for(int i=cur[s];i;i=edge[i].next){
cur[s]=i;
if(dep[edge[i].to]==dep[s]+1&&(f=dfs(edge[i].to,t,min(limit,edge[i].val)))){
ans+=f;
limit-=f;
edge[i].val-=f;
edge[i^1].val+=f;
if(!limit)break;
}
}
return ans;
}
ll dinic(int s,int t){
ll ans=0;
while(bfs(s,t)!=-1)
ans+=dfs(s,t,0x3f3f3f3f);
return ans;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);std::cout.tie(0);
int m,s,t;
std::cin>>n>>m>>s>>t;
for(int i=0,u,v,val;i<m;i++){
std::cin>>u>>v>>val;
add(u,v,val);add(v,u,0);
}
std::cout<<dinic(s,t);
}