#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 10010;
const int M = 200010; //由于残留网络有反向边,乘二
const int INF = 1e12;//无穷大,给个大点的数即可
int n,m,S,T;//n为点数,m为边数,S为源点,T为汇点
/*存储用邻接表来存*/
int h[N];//表头
int e[M];//邻点
int f[M];//注意!!这里是容量
//代码中f表示为当前残留网络的容量
int ne[M],idx;
int q[N];//队列
int d[N];//层数,因为要建立分层图防止环路存在dfs死循环
int cur[N];//当前弧优化
void add(int a,int b,int c)
//考虑建立反向边,注意反向边容量为0
{
e[idx]=b,f[idx]=c,ne[idx]=h[a],h[a]=idx++;
e[idx]=a,f[idx]=0,ne[idx]=h[b],h[b]=idx++;
}
bool bfs(){
int hh=0,tt=0;
memset(d,-1,sizeof(d));
q[0]=S;//起点为源点
d[S]=0;//层数归零
cur[S]=h[S];//弧初始化
while(hh<=tt){
int t=q[hh++];//取出对头元素
for(int i=h[t];~i;i=ne[i]){
int ver=e[i];
if(d[ver]==-1&&f[i])//如果当前点没有被搜过且容量大于零
{
d[ver]=d[t]+1;//层数+1
cur[ver]=h[ver];
if(ver==T)//如果已经找到了终点(汇点)
return true;
q[++tt]=ver;
}
}
}
return false;
}
int find(int u,int limit)
//从u开始搜
//从源点流向u的最大流量
{
if(u==T) return limit;
int flow=0;//表示u往后流的最多流量
for(int i=cur[u];~i&&flow<limit;i=ne[i]){
cur[u]=i;//当前弧优化
int ver=e[i];
if(d[ver]==d[u]+1&&f[i]){
int t=find(ver,min(f[i],limit-flow));
if(!t) d[ver]=-1;//删掉这条边
f[i]-=t;
f[i^1]+=t;//反向弧加上t
flow+=t;
}
}
return flow;
}
int dinic(){
int r=0;//累加流量
int flow;
while(bfs()){
while(flow=find(S,INF)){
r+=flow;
}
}
return r;
}
signed main(){
cin>>n>>m>>S>>T;
memset(h,-1,sizeof h);
while(m--){
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
}
cout<<dinic()<<endl;
return 0;
}