// Generated with assistance from ChatGPT (OpenAI). // Experimental Sorting Flow variant based on arXiv:1302.3035v1. // The claimed O(M sqrt(N)) bound is not established here. #include using namespace std; using ll = long long; struct SortingFlow { struct Edge { int from, to, next_in; ll cap; }; int n; vector edges; vector in_head; explicit SortingFlow(int n, int m = 0) : n(n), in_head(n, -1) { edges.reserve(2 * m); } void add_edge(int u, int v, ll cap) { int k = (int)edges.size(); edges.push_back({u, v, in_head[v], cap}); in_head[v] = k; edges.push_back({v, u, in_head[u], 0}); in_head[u] = k + 1; } ll flow(int s, int t) { if (s == t) return 0; vector excess(n, 0); // Initial preflow: saturate original outgoing edges of s. for (int k = 0; k < (int)edges.size(); k += 2) { if (edges[k].from != s) continue; ll x = edges[k].cap; edges[k].cap -= x; edges[k ^ 1].cap += x; excess[edges[k].to] += x; excess[s] -= x; } vector seen(n, 0), done(n, 0), bfs_order(n); vector first(n), last(n), next_ord(edges.size()); int stamp = 0; while (true) { ++stamp; fill(first.begin(), first.end(), -1); int h = 0, z = 0; bfs_order[z++] = t; seen[t] = stamp; bool active = false; // Reverse BFS; all registered arcs go to earlier BFS vertices. while (h < z) { int v = bfs_order[h++]; done[v] = stamp; if (v != s && v != t && excess[v] > 0) active = true; for (int e = in_head[v]; e != -1; e = edges[e].next_in) { if (edges[e].cap == 0) continue; int u = edges[e].from; if (done[u] == stamp) continue; next_ord[e] = -1; if (first[u] == -1) first[u] = e; else next_ord[last[u]] = e; last[u] = e; if (seen[u] != stamp) { seen[u] = stamp; bfs_order[z++] = u; } } } if (!active) break; // Reverse BFS order is a topological order of the chosen DAG. // Each vertex is discharged once, without an active deque. for (int i = z - 1; i >= 0; --i) { int v = bfs_order[i]; if (v == s || v == t || excess[v] == 0) continue; for (int e = first[v]; e != -1 && excess[v] > 0; e = next_ord[e]) { ll x = min(excess[v], edges[e].cap); if (x == 0) continue; edges[e].cap -= x; edges[e ^ 1].cap += x; excess[v] -= x; excess[edges[e].to] += x; } } } return excess[t]; } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N, M, S, T; cin >> N >> M >> S >> T; --S; --T; SortingFlow mf(N, M); for (int i = 0; i < M; ++i) { int u, v; ll c; cin >> u >> v >> c; mf.add_edge(u - 1, v - 1, c); } cout << mf.flow(S, T) << '\n'; }