#include using namespace std; struct Edge { long long int to; long long int flow; long long int cap; long long int index; Edge(long long int to, long long int flow, long long int cap, long long int index) : to(to), flow(flow), cap(cap), index(index) {} bool isAvailable() { return cap > flow; } long long int getResidue() { return cap - flow; } }; class Flow { private: long long int V, E, S, T; long long int *excess; long long int *height; vector *graph; queue active; long long int *positionInAdj; long long int counter; public: Flow(long long int V, long long int E) { Flow::V = V; Flow::E = E; Flow::graph = new vector[Flow::V + 1]; Flow::excess = new long long int[Flow::V + 1]; Flow::height = new long long int[Flow::V + 1]; Flow::positionInAdj = new long long int[Flow::V + 1]; counter = 0; } virtual ~Flow() { delete[] Flow::graph; delete[] Flow::excess; delete[] Flow::height; delete[] Flow::positionInAdj; } void addEdge(long long int from, long long int to, long long int cap); void setSource(long long int S); void setSink(long long int T); void clearPositionInAdj(); long long int getFlow(); void bfs(long long int start); void preFlow(); void relabel(long long int u); void discharge(long long int u); void push(long long int u, Edge &edge); void globalRelabeling(); }; void Flow::addEdge(long long int from, long long int to, long long int cap) { Edge edgeOne(to, 0, cap, (long long int) graph[to].size()); Edge edgeTwo(from, 0, 0, (long long int) graph[from].size()); graph[from].push_back(edgeOne); graph[to].push_back(edgeTwo); } void Flow::setSource(long long int S) { Flow::S = S; } void Flow::setSink(long long int T) { Flow::T = T; } void Flow::clearPositionInAdj() { for (long long int i = 1; i <= Flow::V; i++) { Flow::positionInAdj[i] = 0; } } void Flow::bfs(long long int start) { Flow::height[start] = Flow::V * (start == Flow::S); queue temp; temp.push(start); while (!temp.empty()) { long long int r = temp.front(); temp.pop(); for (auto &v : graph[r]) { Edge backward = graph[v.to][v.index]; if (Flow::height[v.to] == 2 * Flow::V && backward.isAvailable()) { Flow::height[v.to] = Flow::height[r] + 1; temp.push(v.to); } } } } long long int Flow::getFlow() { Flow::clearPositionInAdj(); for (long long int i = 1; i <= Flow::V; i++) { Flow::height[i] = 0; } Flow::height[S] = V; Flow::preFlow(); while (!active.empty()) { long long int current = Flow::active.front(); Flow::active.pop(); Flow::discharge(current); } return Flow::excess[Flow::T]; } void Flow::preFlow() { for (long long int i = 1; i <= Flow::V; i++) { Flow::excess[i] = 0; } Flow::excess[Flow::S] = LONG_LONG_MAX; for (auto &v : graph[Flow::S]) { Flow::push(Flow::S, v); if (v.to != Flow::T) { Flow::active.push(v.to); } } } void Flow::relabel(long long int u) { Flow::height[u] = LONG_LONG_MAX; for (auto &v : graph[u]) { if (v.isAvailable()) { Flow::height[u] = min(Flow::height[u], Flow::height[v.to]); } } Flow::height[u] += 1; Flow::counter++; if (Flow::counter > Flow::V) { Flow::globalRelabeling(); Flow::counter = 0; } } void Flow::push(long long int u, Edge &edge) { long long int flow = min(Flow::excess[u], edge.getResidue()); Flow::excess[u] -= flow; Flow::excess[edge.to] += flow; edge.flow += flow; graph[edge.to][edge.index].flow -= flow; } void Flow::discharge(long long int u) { while (Flow::excess[u] > 0) { if (Flow::positionInAdj[u] != graph[u].size()) { if (graph[u][Flow::positionInAdj[u]].isAvailable() && Flow::height[u] > Flow::height[graph[u][Flow::positionInAdj[u]].to]) { long long int e = graph[u][Flow::positionInAdj[u]].to; Flow::push(u, graph[u][Flow::positionInAdj[u]]); if (e != Flow::S && e != Flow::T) { Flow::active.push(e); } } else { Flow::positionInAdj[u]++; } } else { Flow::relabel(u); Flow::active.push(u); Flow::positionInAdj[u] = 0; } } } void Flow::globalRelabeling() { for (long long int i = 1; i <= Flow::V; i++) { Flow::height[i] = 2 * Flow::V; } Flow::bfs(Flow::T); Flow::bfs(Flow::S); } int main() { ios_base::sync_with_stdio(false); long long int z; cin >> z; while (z--) { long long int n, m, s, t; cin >> n >> m >> s >> t; Flow flow(n, m); flow.setSource(s); flow.setSink(t); map, long long int> edge; for (long long int i = 1; i <= m; i++) { long long int a, b; long long int c; cin >> a >> b >> c; map, long long int>::iterator it = edge.find(make_pair(a, b)); if (it != edge.end()) { it->second = it->second + c; } else { edge[make_pair(a, b)] = c; } } for (map, long long int>::iterator it = edge.begin(); it != edge.end(); it++) { flow.addEdge(it->first.first, it->first.second, it->second); } cout << flow.getFlow() << endl; } return 0; }