#include <bits/stdc++.h>
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<Edge> *graph;
queue<long long int> 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<Edge>[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<long long int> 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<pair<long long int, long long int>, 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<pair<long long int, long long int>, 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<pair<long long int, long long int>, 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;
}