#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 41;
int n, m, k, eid, res, eido;
char MAP[MAXN][MAXN];
int magf[MAXN][MAXN], magt[MAXN*MAXN];
int revf[MAXN][MAXN], revt[MAXN*MAXN];
int ids[MAXN*MAXN], path[MAXN*MAXN], Time, len;
int p0[MAXN*MAXN], p1[MAXN*MAXN], p2[MAXN*MAXN], sores[MAXN*MAXN];
int dir[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
int dist[MAXN*MAXN];
bool vist[MAXN*MAXN];
bool hash[MAXN*MAXN][MAXN*MAXN];
struct Edge
{
int f,v, next, cost;
};
Edge e[MAXN*MAXN];
Edge orie[MAXN*MAXN*10], orit[MAXN*MAXN*10];
void insert(int from, int to, int cost)
{
e[eid].f = from;
e[eid].v = to;
e[eid].cost = cost;
e[eid].next = p0[from];
p0[from] = eid++;
}
void insert_ori(int from, int to)
{
orie[eido].v = to;
orie[eido].next = p1[from];
p1[from] = eido;
orit[eido].v = from;
orit[eido].next = p2[to];
p2[to] = eido++;
}
void dfs(int pos)
{
int i;
vist[pos] = true;
for (i = p1[pos]; i != -1; i = orie[i].next)
{
if (!vist[orie[i].v])
{
dfs(orie[i].v);
}
}
path[len++] = pos;
}
void dfs_reverse(int pos)
{
vist[pos] = true;
ids[pos] = Time;
int x = pos/m, y = pos%m;
if (MAP[x][y] >= '1' && MAP[x][y] <= '9')
{
sores[Time] += MAP[x][y]-'0';
}
int i;
for (i = p2[pos]; i != -1; i = orit[i].next)
{
if (!vist[orit[i].v])
{
dfs_reverse(orit[i].v);
}
}
}
void floodfill()
{
bool flag = true;
int i;
for (i = 1; i < Time; ++i)
{
dist[i] = 0;
}
while (flag)
{
flag = false;
for (i = 0; i < eid; ++i)
{
if (dist[e[i].v] + e[i].cost > dist[e[i].f])
{
dist[e[i].f] = dist[e[i].v] + e[i].cost;
flag = true;
}
}
}
printf("%d\n", dist[ids[0]]+res);
}
void debug()
{
int i, j;
for (i = 0; i < n; ++i)
{
for (j = 0; j < m; ++j)
{
printf("%d ", ids[i*m+j]);
}
printf("\n");
}
}
void solution()
{
len = 0, Time = 1;
int i, j, q, fx, fy;
for (i = 0; i < n*m; ++i)
{
vist[i] = false;
ids[i] = 0;
}
for (i = 0; i < n; ++i)
{
for (j = 0; j < m; ++j)
{
if (!vist[i*m+j] && MAP[i][j] != '#')
{
dfs(i*m+j);
}
}
}
for (i = 0; i < n*m; ++i)
{
vist[i] = false;
}
sores[0] = 0;
for (i = len-1; i >= 0; --i)
{
int x, y;
x = path[i]/m;
y = path[i]%m;
if (!vist[path[i]] && MAP[x][y] != '#')
{
sores[Time] = 0;
dfs_reverse(path[i]);
Time++;
}
}
for (i = 1; i < Time; ++i)
{
p0[i] = -1;
for (j = 1; j < Time; ++j)
{
hash[i][j] = false;
}
}
eid = 0;
res = sores[ids[0]];
for (i = 0; i < n; ++i)
{
for (j = 0; j < m; ++j)
{
if (MAP[i][j] != '#')
{
for (q = 0; q < 2; ++q)
{
fx = i + dir[q][0];
fy = j + dir[q][1];
if (fx >= 0 && fx < n && fy >= 0 && fy < m && MAP[fx][fy] != '#')
{
if (ids[fx*m+fy] != ids[i*m+j] && !hash[ids[i*m+j]][ids[fx*m+fy]])
{
hash[ids[i*m+j]][ids[fx*m+fy]] = true;
insert(ids[i*m+j], ids[fx*m+fy], sores[ids[fx*m+fy]]);
}
}
}
if (MAP[i][j] == '*')
{
int pot = magt[magf[i][j]];
fx = pot/m;
fy = pot%m;
if (MAP[fx][fy] != '#')
{
if (ids[i*m+j] != ids[fx*m+fy] && !hash[ids[i*m+j]][ids[fx*m+fy]])
{
hash[ids[i*m+j]][ids[fx*m+fy]] = true;
insert(ids[i*m+j], ids[fx*m+fy], sores[ids[fx*m+fy]]);
}
}
}
}
}
}
floodfill();
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d %d", &n, &m);
int i, j, q;
k = 0;
for (i = 0; i < n; ++i)
{
for (j = 0; j < m; ++j)
{
revf[i][j] = -1;
}
}
getchar();
for (i = 0; i < n; ++i)
{
gets(MAP[i]);
for (j = 0; j < m; ++j)
{
if (MAP[i][j] == '*')
{
magf[i][j] = k;
revt[k++] = i*m+j;
}
}
}
eido = 0;
memset(p1, -1, sizeof(p1));
memset(p2, -1, sizeof(p2));
for (i = 0; i < k; ++i)
{
int x, y;
scanf("%d %d", &x, &y);
magt[i] = x*m+y;
revf[x][y] = i;
insert_ori(revt[i], magt[i]);
}
for (i = 0; i < n; ++i)
{
for (j = 0; j < m; ++j)
{
if (MAP[i][j] != '#')
{
for (q = 0; q < 2; ++q)
{
int fx, fy;
fx = i + dir[q][0];
fy = j + dir[q][1];
if (fx >= 0 && fx < n && fy >= 0 && fy < m && MAP[fx][fy] != '#')
{
insert_ori(i*m+j, fx*m+fy);
}
}
}
}
}
solution();
}
return 0;
}