#define comein freopen("in.txt", "r", stdin);
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
#define INF 1<<30
#define N 2000
int eid;
int head[N], to[N], cap[N], next[N];
int level[N];
void add_edge(int from, int t, int f)
{
to[eid] = t;
cap[eid] = f;
next[eid] = head[from];
head[from] = eid++;
to[eid] = from; //建反向边
cap[eid] = 0;
next[eid] = head[t];
head[t] = eid++;
}
bool bfs(int root, int n_point) //残余网络分层
{
memset(level, -1, sizeof(level));
queue<int>que;
que.push(root);
level[root] = 0;
while(!que.empty())
{
root = que.front();
que.pop();
for(int i = head[root]; i != -1; i = next[i])
{ //边还有残余容量,且下一个点还没分层
if(level[to[i]] == -1 && cap[i])
{
level[to[i]] = level[root] + 1;
if(to[i] == n_point)
return true;
que.push(to[i]);
}
}
}
return false;
}
int dfs(int root, int f, int n_point)
{
if(root == n_point)
return f;
int flow, ans = 0;
for(int i = head[root]; i != -1; i = next[i])
{
int m = min(cap[i], f - ans);
if(cap[i] && level[root]+1 == level[to[i]] &&
(flow = dfs(to[i], m, n_point ) ) )
{ //下标从0开始,则正向边为偶数,反向边为基数;
cap[i] -= flow;
cap[i^1] += flow;//下标从1开始则不能用 异或
ans += flow;
}
}
if(ans == 0) //若没找到增广路,这时注意要把该点
level[root] = -1; //的层次标为-1,表示不能到达
return ans;
}
void dinic(int n_point)
{
int flow = 0;
while(bfs(1, n_point)) //分层
{
while(1) //每条增广路都有一个瓶颈(增光路上最小容量的边)
{ //每次分层都要把所有增广路的瓶颈都清除掉,再重新分层
int f = dfs(1, INF, n_point);//因此最多层分v次
if(f == 0)
break;
flow += f;
}
}
printf("%d\n", flow);
}
int main()
{
eid = 0;
int n_case;
scanf("%d", &n_case);
for(int t = 1; t <= n_case; ++t)
{
printf("Case %d: ", t);
int n_point, n_edge;
scanf("%d%d", &n_point, &n_edge);
memset(head, -1, sizeof(head));
while(n_edge--)
{
int from, to, f;
scanf("%d%d%d", &from, &to, &f);
add_edge(from, to, f);
}
dinic(n_point);
}
return 0;
}