#include<bits/stdc++.h>
using namespace std;
const int N=12e2+10,M=12e4+10;
int n,m,s,t;
int cnt=1;
struct Edge { int to,rev,w; } edge[M];
int degree[N],first_edge[N],cur_edge[N];
int front,q[N];
int heightest,gapHeightest,height[N];
int gapPre[N<<1],gapNxt[N<<1];
int lst[N],nxt[N];
int f[N];
int work;
vector<array<int,3> > e(M);
int ans;
inline bool cmp(Edge x,Edge y) { return x.to<y.to; }
inline int read(){
int X=0; bool flag=1; char ch=getchar();
while(ch<'0' || ch>'9') { if(ch=='-') flag=0; ch=getchar(); }
while(ch>='0' && ch<='9') { X=(X<<1)+(X<<3)+ch-'0'; ch=getchar(); }
if(flag) return X;
return ~(X-1);
}
inline void add(int u,int v,int w){
edge[cur_edge[u]++]={v,cur_edge[v],w};
edge[cur_edge[v]++]={u,cur_edge[u]-1,0};
}
inline void PushLst(int u){
int h=height[u];
nxt[u]=lst[h];
lst[h]=u;
}
inline void UpdHeight(int u,int h){
if(height[u]!=n){
gapNxt[gapPre[u]]=gapNxt[u];
gapPre[gapNxt[u]]=gapPre[u];
}
if(h==n) return ;
height[u]=h;
gapHeightest=max(gapHeightest,h);
if(f[u]){
PushLst(u);
heightest=max(heightest,h);
}
h+=n;
gapPre[u]=h;
gapNxt[u]=gapNxt[h];
gapNxt[h]=u;
gapPre[gapNxt[u]]=u;
}
inline void GlobalRelabel(){
fill(height+1,height+1+n,n);
work=0;
height[t]=0;
q[++front]=t;
for(int i(1);i<=front;i++){
int u=q[i];
for(int j(first_edge[u]);j<(first_edge[u+1]);j++){
auto& e=edge[j];
int v=e.to,w=e.w;
if(height[v]==n && w){
UpdHeight(v,height[u]+1);
q[++front]=v;
}
}
}
heightest=height[q[front]];
}
inline void Push(int u,Edge &e){
int v=e.to,rev=e.rev,&w=e.w,flow=min(f[u],w);
if(flow){
if(!f[v] && v!=s && v!=t) PushLst(v);
w-=flow; edge[rev].w+=flow;
f[u]-=flow; f[v]+=flow;
}
}
inline void Discharge(int u){
++work;
int h=n;
for(int i(cur_edge[u]);i<cur_edge[i+1];cur_edge[u]++,i++){
auto& e=edge[i];
int v=e.to,w=e.w;
if(w){
if(height[u]==height[v]+1){
Push(u,e);
if(!f[v]) break;
}
else h=min(h,height[u]+1);
}
}
if(gapNxt[gapNxt[height[u]+n]]!=height[u]+n) UpdHeight(u,h);
else {
for(int i(height[u]);i<=heightest;i++){
for(int j(gapNxt[height[u]+n]);j<n;j=gapNxt[j]){
height[j]=n;
}
}
gapHeightest=height[u]-1;
}
}
inline void HLPP(){
for(int u(1);u<=n;u++){
sort(edge+first_edge[u],edge+first_edge[u+1]-1,cmp);
for(int i(first_edge[u]);i<first_edge[u+1];i++){
auto& e=edge[i];
int rev=e.rev;
edge[rev].rev=i;
}
}
GlobalRelabel();
for(int i(first_edge[s]);i<first_edge[s+1];i++){
auto& e=edge[i];
int v=e.to,rev=e.rev,&w=e.w;
edge[rev].w+=w; f[v]+=w;
w-=w;
}
copy(first_edge+1,first_edge+1+n,cur_edge);
for(;heightest;heightest--){
for(int u(lst[heightest]);u;u=nxt[u]){
if(height[u]==heightest){
Discharge(u);
if(work>=n<<2) GlobalRelabel();
}
}
}
}
int main(){
n=read(); m=read(); s=read(); t=read();
for(auto x:e){
x[0]=read(); x[1]=read(); x[2]=read();
degree[x[0]]++; degree[x[1]]++;
}
for(int i(1);i<=n;i++){
first_edge[i]=cnt;
cnt+=degree[i];
}
first_edge[n+1]=cnt;
copy(first_edge+1,first_edge+2+n,cur_edge);
for(auto x:e) add(x[0],x[1],x[2]);
HLPP();
printf("%d\n",f[t]);
return 0;
}