EK
//EK
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3+1,M = 2e4+1,INF = 1e9+7;
int n,m,S,T;
struct op{
int nxt,f/*容量*/,to;
}e[M];
int head[N],NUM;
int d[N]/*当前点所有边容量的最小值*/,pre[N]/*前驱*/;
bool vis[N]/*判重*/;
void add(int frm,int to,int dis) {
e[NUM] = op{head[frm],dis,to}; head[frm] = NUM++;
e[NUM] = op{head[to],0,frm}; head[to] = NUM++;
}//边从0开始编号,方便边^1来表示下一条边,head数组初始化为-1
bool bfs() {//找增广路
queue<int>q;
memset(vis,0,sizeof vis);
q.push(S); vis[S] = 1; d[S] = INF;
while(!q.empty()) {
int x = q.front();q.pop();
for(int i = head[x];~i;i = e[i].nxt) {
int v = e[i].to;
if(!vis[v]&&e[i].f) {//可以更新
vis[v] = 1;
d[v] = min(d[x],e[i].f);//更新最小值
pre[v] = i;//这个点的前驱边
if(v == T) return 1;
q.push(v);
}
}
}
return 0;
}
int EK() {
int res = 0;
while(bfs()) {//1.更新增广路
res += d[T];
for(int i = T;i != S;i = e[pre[i]^1].to) {
e[pre[i]].f -= d[T];//当前边容量减少
e[pre[i]^1].f += d[T];//反向边容量增加
}//2.更新残留网络
}
return res;
}
int main() {
cin>>n>>m>>S>>T;
memset(head,-1,sizeof head);
while(m--) {
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
}
cout<<EK();
return 0;
}
Dinic
//Dinic
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4+1,M = 2e5+1,INF = 1e9+7;
int n,m,S,T;
struct op{
int to,nxt,f;
}e[M];
int head[M],NUM;
int d[M]/*层数*/,cur[M]/*当前弧优化*/;
//在邻接表枚举当前点的所有边的时候,会按顺序分配,即某些边会满
//那么下一次搜到这个点的时候就可直接跳过
void add(int frm,int to,int w) {
e[NUM] = op{to,head[frm],w}; head[frm] = NUM++;
e[NUM] = op{frm,head[to],0}; head[to] = NUM++;
}
//其余同EK
bool bfs() {//找增广路同时建立分层图
queue<int>q;
memset(d,-1,sizeof d);
q.push(S); d[S] = 0; cur[S] = head[S]/*从第一条边开始走*/;
while(!q.empty()) {
int x = q.front(); q.pop();
for(int i = head[x];~i;i = e[i].nxt) {
int v = e[i].to;
if(d[v] == -1&&e[i].f) {
d[v] = d[x] + 1;//当前层数 = 上一层数 + 1
cur[v] = head[v];//这个点的当前弧是第一条边
if(v == T) return 1;
q.push(v);
}
}
}
return 0;
}
int find(int u,int limit) {//从S流向u最大的流量为limit
if(u == T) return limit;
int flow = 0;//从u往后流的最大流量为flow
for(int i = cur[u]/*从当前没有满的路径开始*/;~i&&flow<limit;i = e[i].nxt) {
cur[u] = i;//i之前的边都满了
int v = e[i].to;
if(d[v] == d[u] + 1&&e[i].f) {//当前点是在上一个点的下一层
int x = find(v,min(e[i].f,limit-flow));
if(!x) d[v] = -1;//如果当点不可用(没有路径)就删掉
e[i].f -= x; e[i^1].f += x;//当前边减去流量,反向边加上流量
flow += x;//最大流量加上这些流量
}
}
return flow;
}
int dinic() {
int res = 0,flow;
while(bfs())//只要它有增广路径
while(flow = find(S,INF))//就全部找出来
res += flow;//把总共能加的流量加起来
//下次迭代继续找剩余的增广路
return res;
}
int main() {
memset(head,-1,sizeof head);
cin>>n>>m>>S>>T;
while(m--) {
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
}
cout<<dinic();
}