#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<bitset>
#define mme(a,b) memset((a),(b),sizeof((a)))
#define precision(x,d) cout<<fixed<<setprecision(d)<<x<<"\n"
#define iis std::ios::sync_with_stdio(false)
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int N = 1e5+5;
int n,m;
const int MAXN = 1e4+105;
const int MAXE = 4e5+7;
struct lp {
int v,nex;
int cap,flow;
} cw[MAXE];
int vs,vt,NE,NV;
int head[MAXN],pre[MAXN],cur[MAXN],level[MAXN],gap[MAXN];
inline void add_edge(int u,int v,int cap){
cw[NE].v = v;cw[NE].cap = cap;cw[NE].flow = 0;cw[NE].nex = head[u];
head[u] = NE++;
cur[u] = head[u];
cw[NE].v = u;cw[NE].cap = 0;cw[NE].flow = 0;cw[NE].nex = head[v];
head[v] = NE++;
cur[v] = head[v];
}
inline void bfs(int vt){
memset(level,-1,sizeof(level));
memset(gap,0,sizeof(gap));
level[vt]=0;
gap[level[vt]]++;
queue<int>que;
que.push(vt);
while(!que.empty()) {
int u=que.front();
que.pop();
for(int i=head[u]; i!=-1; i=cw[i].nex) {
int v=cw[i].v;
if(level[v]!=-1)continue;
level[v]=level[u]+1;
gap[level[v]]++;
que.push(v);
}
}
}
int SAP(int vs,int vt){
bfs(vt);
memset(pre,-1,sizeof(pre));
//for(int i=0;i<=n;++i)cur[i]=head[i];
int u=pre[vs]=vs,flow=0,aug=INF;
gap[0]=NV;
while(level[vs]<NV) {
bool flag=false;
for(int &i=cur[u]; i!=-1; i=cw[i].nex) {
int v=cw[i].v;
if(cw[i].cap>cw[i].flow&&level[u]==level[v]+1) {
flag=true;
pre[v]=u;
u=v;
// aug=(aug==-1?cw[i].cap:min(aug,cw[i].cap));
aug=min(aug,cw[i].cap-cw[i].flow );
if(v==vt) {
flow+=aug;
for(u=pre[v]; v!=vs; v=u,u=pre[u]) {
cw[cur[u]].flow+=aug;
cw[cur[u]^1].flow-=aug;
}
// aug=-1;
aug=INF;
}
break;
}
}
if(flag)continue;
int minlevel=NV;
for(int i=head[u]; i!=-1; i=cw[i].nex) {
int v=cw[i].v;
if(cw[i].cap>cw[i].flow&&level[v]<minlevel) {
minlevel=level[v];
cur[u]=i;
}
}
if(--gap[level[u]]==0)break;
level[u]=minlevel+1;
gap[level[u]]++;
u=pre[u];
}
return flow;
}
void init(){
NE=0;NV=n;
//vs=1;vt=n;
memset(head,-1,sizeof(head));
memset(cur,-1,sizeof(cur));
}
int main(){
int u,v,w;
scanf("%d%d%d%d",&n,&m,&vs,&vt);
init();
for(int i=1; i<=m; i++) {
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
}
printf("%d\n",SAP(vs,vt));
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<bitset>
#define mme(a,b) memset((a),(b),sizeof((a)))
#define precision(x,d) cout<<fixed<<setprecision(d)<<x<<"\n"
#define iis std::ios::sync_with_stdio(false)
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int MXN = 1e4+7;
const int MXE = 4e5+7;
int vs, vt;
struct DINIC{
int tot,vt,vs;
int d[MXN],head[MXN];
struct lp{
int v,w,nex;
}cw[MXE];
void add_edge(int a,int b,int c){
cw[++tot].v=b;cw[tot].nex=head[a],cw[tot].w=c;
head[a]=tot;
cw[++tot].v=a;cw[tot].nex=head[b],cw[tot].w=0;
head[b]=tot;
}
bool bfs(){
memset(d,-1,sizeof(d));
queue<int>Q;
Q.push(vt);d[vt]=0;
while(!Q.empty()){
int u=Q.front();
Q.pop();
for(int i=head[u];i!=-1;i=cw[i].nex){
int v=cw[i].v;
if(cw[i^1].w&&d[v]==-1){
d[v]=d[u]+1;
Q.push(v);
}
}
}
return d[vs]!=-1;
}
/*int dfs(int x,int low){
if(x==vt||low==0)return low;
int flow=0,used=0;
for(int i=head[x];i!=-1;i=cw[i].nex){
int v=cw[i].to;
if(cw[i].w&&d[v]+1==d[x]&&(used=dfs(v,min(low,cw[i].w)))>0){
//used=dfs(v,min(low,cw[i].w));
if(!used)continue;
flow+=used,low-=used;
cw[i].w-=used;cw[i^1].w+=used;
if(!low)break;
}
}
if(!flow)d[x]=-1;
return flow;
}*/
int dfs(int x,int f){
if(x==vt||f==0) return f;
int use=0,w;
for(int i=head[x];i!=-1;i=cw[i].nex){
int to=cw[i].v;
if(d[to]==d[x]-1 && cw[i].w){
w=dfs(to,min(cw[i].w,f-use));
cw[i].w-=w,cw[i^1].w+=w;
use+=w;
if(use==f) return f;
}
}
if(!use)d[x]=-1;
return use;
}
void init(int st,int ed){
tot=-1;
memset(head,-1,sizeof(head));
vs=st;vt=ed;
}
int max_flow(){
int ans=0;
while(bfs())ans+=dfs(vs,INF);
return ans;
}
}dinic;
int main(){
int u,v,w,n,m;
scanf("%d%d%d%d",&n,&m,&vs,&vt);
dinic.init(vs,vt);
for(int i=1; i<=m; i++) {
scanf("%d%d%d",&u,&v,&w);
dinic.add_edge(u,v,w);
}
printf("%d\n",dinic.max_flow());
return 0;
}
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include <cstdio>
#include <cstring>
using namespace std;
const int inf = 0x3fffffff;
template <int N, int M>
struct Isap{
int top;
int d[N], pre[N], cur[N], gap[N];
struct Vertex {
int head;
} V[N];
struct Edge {
int v, next;
int c, f;
} E[M];
void init() {
memset(V, -1, sizeof(V));
top = 0;
}
void add_edge(int u, int v, int c) {
E[top].v = v;
E[top].c = c;
E[top].f = 0;
E[top].next = V[u].head;
V[u].head = top++;
}
void add(int u, int v, int c) {
add_edge(u, v, c);
add_edge(v, u, 0);
}
void set_d(int t) {
queue<int> Q;
memset(d, -1, sizeof(d));
memset(gap, 0, sizeof(gap));
d[t] = 0;
Q.push(t);
while (!Q.empty()) {
int v = Q.front(); Q.pop();
++gap[d[v]];
for (int i = V[v].head; ~i; i = E[i].next) {
int u = E[i].v;
if (d[u] == -1) {
d[u] = d[v] + 1;
Q.push(u);
}
}
}
}
int sap(int s, int t, int num) {
set_d(t);
int ans = 0, u = s;
int flow = inf;
memcpy(cur, V, sizeof(V));
while (d[s] < num) {
int &i = cur[u];
for (; ~i; i = E[i].next) {
int v = E[i].v;
if (E[i].c > E[i].f && d[u] == d[v] + 1) {
u = v;
pre[v] = i;
flow = min(flow, E[i].c - E[i].f);
if (u == t) {
while (u != s) {
int j = pre[u];
E[j].f += flow;
E[j ^ 1].f -= flow;
u = E[j ^ 1].v;
}
ans += flow;
flow = inf;
}
break;
}
}
if (i == -1) {
if (--gap[d[u]] == 0)
break;
int dmin = num - 1;
cur[u] = V[u].head;
for (int j = V[u].head; ~j; j = E[j].next)
if (E[j].c > E[j].f)
dmin = min(dmin, d[E[j].v]);
d[u] = dmin + 1;
++gap[d[u]];
if (u != s)
u = E[pre[u] ^ 1].v;
}
}
return ans;
}
};
Isap<200005, 400005> Sap;
int tux[100001], tuy[100001],st,zt;
int main(){
int n, m;
scanf("%d%d%d%d", &n, &m, &st, &zt);
int q, w, e;
Sap.init();
for (int a = 1; a <= m; a++){
scanf("%d%d%d", &q, &w, &e);
Sap.add(q, w, e);
}
printf("%d\n",Sap.sap(st, zt, 9 * m + 2));
return 0;
}