#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll Maxn=2.2e5+7,inf=4557430888798830399;
ll n,m,s,t;
namespace IO{
template <typename T,typename... Args>inline istream& qread(T &x){return cin>>x;}
template<typename T, typename... Args>inline ostream& write(const T& t){return cout<<t;}
template <typename T,typename... Args>
inline istream& qread(T &x,Args &... rest){
cin>>x;
return qread(rest...);
}
template <typename T,typename ... Args>
inline ostream& write(const T& t1,const Args&... rest){
cout<<t1;
return write(rest...);
}
}
using namespace IO;
struct edge1{
ll u,v,w;
}ve[Maxn];
class Dinic{
public:
inline void modify(ll x){
v[e[x].v].push_back(x*2+1);
}
inline void addEdge(ll u,ll v1,ll w){
e.push_back(edge1{u,v1,w});
e.push_back(edge1{v1,u,0});
v[u].push_back(e.size()-2);
}
inline ll dinic(){
ll ans=0;
while(bfs()){
memset(now,0,sizeof now);
ans+=dfs(s,inf);
}
return ans;
}
private:
vector<ll>v[Maxn];
vector<edge1>e;
ll dis[Maxn],now[Maxn],que[Maxn];
inline bool bfs(void){
memset(dis,0x3f,sizeof dis);
ll l=1,r=1;que[1]=s;dis[s]=0;
while(l<=r){
ll p=que[l++],to;
for(ll i:v[p])
if(e[i].w&&dis[to=e[i].v]>1e9)
dis[to]=dis[p]+1,que[++r]=to;
}
return dis[t]<1e9;
}
ll dfs(ll u,ll flow){
if(u==t||!flow) return flow;
ll sf=0,flw;
for(ll &i=now[u],to;i<(ll)v[u].size();++i){
edge1 &E=e[v[u][i]];
if(dis[to=E.v]==dis[u]+1&&(flw=dfs(to,min(flow,E.w)))){
E.w-=flw;e[v[u][i]^1].w+=flw;
flow-=flw;sf+=flw;
if(!flow)break;
}
}
return sf;
}
}fx;
ll G;
int main(int argc,char **argv){
qread(n,m,s,t);
for(ll i=0;i<m;i++) qread(ve[i].u,ve[i].v,ve[i].w);
sort(ve,ve+m,[](edge1 x,edge1 y){return x.w>y.w;});
for(ll g:{0,1})
for(ll p=1<<30,i=0;p;p>>=1){
while(i<m&&ve[i].w>=p){
if(g) fx.modify(i);
else fx.addEdge(ve[i].u,ve[i].v,ve[i].w);
++i;
}
G+=fx.dinic();
}
write(G);
return 0;
}