#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t) for (int i=s;i<=t;i++)
#define pi acos(-1)
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<double, double> PDD;
typedef pair<PII, PII> PPP;
typedef pair<PII, int> PPI;
#define repp(i,s,t) for (int i=s;i>=t;i--)
template<class T> T sqr(T x) {return x*x;}
#define debug(x) cerr<<#x"="<<(x)<<endl;
#define pb(x) push_back(x);
#define ori(x) x-'a'
const int maxn = 10001;
PII pre[maxn];
struct edges{int v, flow, rev, cost;} make;
vector<edges> g[maxn];
int dir[5][2];
int a[55][55], b[55][55], c[55][55];
int dist[maxn], vis[maxn];
int st, en, x, y, z, n, m;
inline void addedge(int x, int y, int flow, int cost)
{
	int v1 = g[x].size();
	int v2 = g[y].size();
	make.v = y;
	make.flow = flow;
	make.cost = cost;
	make.rev = v2;
	g[x].push_back(make);
	make.v = x;
	make.flow = 0;
	make.rev = v1;
	make.cost = -cost;
	g[y].push_back(make);
}
inline bool spfa()
{
	rep(i,1,en) dist[i] = 1000000000;
	dist[st] = 0;
	queue<int> q;
	q.push(st);
	while (!q.empty())
	{
		int x = q.front();
		vis[x] = false;
		q.pop();
		for (int i = 0 ;i < g[x].size(); i++)
			if (g[x][i].flow && dist[g[x][i].v] > dist[x] + g[x][i].cost)
			{
				dist[g[x][i].v] = dist[x] + g[x][i].cost;
				pre[g[x][i].v] = PII(x, i);
				if (!vis[g[x][i].v])
				{
					q.push(g[x][i].v);
					vis[g[x][i].v] = 1;
				}
			}
	}
	return dist[en] < 1000000000;
}
int mincut(int x, int fw)
{
	if (x == st) return fw;
	int f = mincut(pre[x].first, min(fw, g[pre[x].first][pre[x].second].flow));
	g[pre[x].first][pre[x].second].flow -= f;
	g[x][g[pre[x].first][pre[x].second].rev].flow += f;
	return f;
}
int main()
{
	dir[0][0] = 0;	dir[0][1] = -1;
	dir[1][0] = -1; dir[1][1] = 0;
	dir[2][0] = 0;	dir[2][1] = 1;
	dir[3][0] = 1;	dir[3][1] = 0;
	int testdata;
	scanf("%d",&testdata);
	rep(_t,1,testdata)
	{
		printf("Case #%d: ", _t);
		scanf("%d%d",&n,&m);
		st = 2 * n * m + 1;
		en = 2 * n * m + 2;
		rep(i,1,en) g[i].clear();
		int tot = 0;
		rep(i,1,n) rep(j,1,m) 
		{
			scanf("%d",&a[i][j]);
			int place = (i - 1) * m + j;
			if (a[i][j] == 0)
			{
				addedge(st, place, 1, 0);
				addedge(n * m + place, en, 1, 0);
				tot++;
			}
			else if (a[i][j] & 1) addedge(st, place, 1, 0), tot++;
			else addedge(place + n * m, en, 1, 0);
		}
		rep(i,1,n-1) rep(j,1,m) scanf("%d",&b[i][j]);
		rep(i,1,n) rep(j,1,m-1) scanf("%d",&c[i][j]);
		rep(i,1,n) rep(j,1,m)
		rep(k,0,3)
		{
			int dx = i + dir[k][0];
			int dy = j + dir[k][1];
			if (dx <= 0 || dx > n || dy <= 0 || dy > m) continue;
			int from = (i - 1) * m + j;
			int to = (dx - 1) * m + dy + n * m;
			int cost;
			if (k == 0) cost = c[i][j-1];
			if (k == 1) cost = b[i-1][j];
			if (k == 2) cost = c[i][j];
			if (k == 3) cost = b[i][j];
			addedge(from , to, 1, cost);
		}
		int totfl = 0;
		int ans = 0;
		while (spfa())
		{
			int fl = mincut(en, 1000000000);
			totfl += fl;
			ans += dist[en] * fl;
		}
		if (totfl != tot) puts("-1");
		else printf("%d\n", ans);
	}
}

