#include #include #include #include #include #include class Dinic { using i64 = std::int64_t; struct Edge { int to, rev; i64 cap; }; std::vector> graph; std::vector level, current; bool bfs(int source, int sink) { std::fill(level.begin(), level.end(), -1); std::queue que; level[source] = 0; que.push(source); while (!que.empty()) { int vertex = que.front(); que.pop(); for (const Edge &edge : graph[vertex]) { if (edge.cap > 0 && level[edge.to] == -1) { level[edge.to] = level[vertex] + 1; que.push(edge.to); } } } return level[sink] != -1; } i64 dfs(int vertex, int sink, i64 pushed) { if (vertex == sink) return pushed; for (int &index = current[vertex]; index < static_cast(graph[vertex].size()); ++index) { Edge &edge = graph[vertex][index]; if (edge.cap == 0 || level[edge.to] != level[vertex] + 1) continue; i64 result = dfs(edge.to, sink, std::min(pushed, edge.cap)); if (result == 0) continue; edge.cap -= result; graph[edge.to][edge.rev].cap += result; return result; } return 0; } public: explicit Dinic(int size) : graph(size), level(size), current(size) {} void addEdge(int from, int to, i64 cap) { int a = static_cast(graph[from].size()); int b = static_cast(graph[to].size()); graph[from].push_back({to, b, cap}); graph[to].push_back({from, a, 0}); } i64 maxFlow(int source, int sink) { i64 result = 0; const i64 infinity = std::numeric_limits::max(); while (bfs(source, sink)) { std::fill(current.begin(), current.end(), 0); while (i64 pushed = dfs(source, sink, infinity)) result += pushed; } return result; } }; int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n, m, source, sink; if (!(std::cin >> n >> m >> source >> sink)) return 0; Dinic flow(n); for (int i = 0; i < m; ++i) { int from, to; std::int64_t cap; std::cin >> from >> to >> cap; flow.addEdge(from - 1, to - 1, cap); } std::cout << flow.maxFlow(source - 1, sink - 1) << '\n'; }