#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
typedef long long LL;
const lint maxn = 10010;
const lint maxm = 10010;
const LL INF = 0x3f3f3f3f3f3f3f3f;
lint tot,ver[maxm],he[maxn],ne[maxm];
LL cost[maxm];
void add( lint x,lint y,lint c ){
ver[++tot]=y;
ne[tot]=he[x];
he[x]=tot;
cost[tot]=c;
}
lint vis2[maxn];
priority_queue< pair<LL,LL>,vector< pair<LL,LL> >,greater< pair<LL,LL> > > que2;
LL dist[maxn],vis[maxn];
void dijkstra( LL S,LL T ){
while( que2.size() ) que2.pop();
dist[S] = 0;
que2.push( make_pair( 0,S ) );
while( que2.size() ){
LL x = que2.top().second;
que2.pop();
//if( x == T ) break;
if( vis[x] ) continue;
vis[x] = 1;
for( LL cure = he[x];cure;cure = ne[cure] ){
LL y = ver[cure];
if( vis[y] ) continue;
if( dist[y] > dist[x] + cost[cure] ){
dist[y] = dist[x] + cost[cure];
que2.push( make_pair( dist[y],y ) );
}
}
}
}
struct Edge {
int from, to;
LL cap, flow;
};
bool operator < (const Edge& a, const Edge& b) {
return a.from < b.from || (a.from == b.from && a.to < b.to);
}
struct ISAP {
int n, m, s, t;
vector<Edge> edges;
vector<int> G[maxn]; // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
bool vis[maxn]; // BFS使用
LL d[maxn]; // 从起点到i的距离
int cur[maxn]; // 当前弧指针
int p[maxn]; // 可增广路上的上一条弧
int num[maxn]; // 距离标号计数
void AddEdge(int from, int to, LL cap) {
edges.push_back((Edge){from, to, cap, 0});
edges.push_back((Edge){to, from, 0, 0});
m = edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool BFS() {
memset(vis, 0, sizeof(vis));
queue<int> Q;
Q.push(t);
vis[t] = 1;
d[t] = 0;
while(!Q.empty()) {
int x = Q.front(); Q.pop();
for(int i = 0; i < G[x].size(); i++) {
Edge& e = edges[G[x][i]^1];
if(!vis[e.from] && e.cap > e.flow) {
vis[e.from] = 1;
d[e.from] = d[x] + 1;
Q.push(e.from);
}
}
}
return vis[s];
}
void ClearAll(int n) {
this->n = n;
for(int i = 0; i <= n; i++) G[i].clear();
edges.clear();
}
void ClearFlow() {
for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;
}
LL Augment() {
int x = t;
LL a = INF;
while(x != s) {
Edge& e = edges[p[x]];
a = min(a, e.cap-e.flow);
x = edges[p[x]].from;
}
x = t;
while(x != s) {
edges[p[x]].flow += a;
edges[p[x]^1].flow -= a;
x = edges[p[x]].from;
}
return a;
}
LL Maxflow(int s, int t) {
this->s = s; this->t = t;
LL flow = 0;
BFS();
memset(num, 0, sizeof(num));
for(int i = 0; i < n; i++) num[d[i]]++;
int x = s;
memset(cur, 0, sizeof(cur));
while(d[s] < n) {
if(x == t) {
flow += Augment();
//if(flow >= need) return flow;
x = s;
}
int ok = 0;
for(int i = cur[x]; i < G[x].size(); i++) {
Edge& e = edges[G[x][i]];
if(e.cap > e.flow && d[x] == d[e.to] + 1) { // Advance
ok = 1;
p[e.to] = G[x][i];
cur[x] = i; // 注意
x = e.to;
break;
}
}
if(!ok) { // Retreat
LL m = n-1; // 初值注意
for(int i = 0; i < G[x].size(); i++) {
Edge& e = edges[G[x][i]];
if(e.cap > e.flow) m = min(m, d[e.to]);
}
if(--num[d[x]] == 0) break;
num[d[x] = m+1]++;
cur[x] = 0; // 注意
if(x != s) x = edges[p[x]].from;
}
}
return flow;
}
};
ISAP g;
void dfs( lint x ){
//vis2[x]=1;
for( lint cure = he[x];cure;cure = ne[cure] ){
if( vis2[cure] ) continue;
vis2[cure] = 1;
lint y = ver[cure];
if( dist[x] + cost[cure] == dist[y] ){
g.AddEdge(y,x,cost[cure]);
}
dfs(y);
}
}
void init( lint n,lint m ){
for( lint i = 1;i <= m+5;i++ ) vis2[i] = 0;
for( lint i = 1; i <= n;i++ ) he[i]=vis[i]=0;
for( lint i = 1;i <= n;i++ ) dist[i] = INF;
tot=1;
}
int main(){
lint T,n,m;
scanf("%lld",&T);
while( T-- ){
scanf("%lld%lld",&n,&m);
init(n,m);
g.ClearAll(n);
lint x,y,c;
for( lint i = 1;i <= m;i++ ){
scanf("%lld%lld%lld",&x,&y,&c);
add( y,x,c );
}
dijkstra(n,1);
if( dist[1] == INF ){
cout << 0 << endl;
continue;
}
dfs(n);
LL ans = g.Maxflow(1,n);
cout << ans << endl;
}
return 0;
}