// 转动电路 -> 边权为1
// 1. 层: 当前(x,y)代价
// 2. 状态: (x,y)-> 斜向映射, (x,y) -> 点面映射
// 3. 剪枝:
// 3.1 最优化:if (d[nx][ny] <= d[x][y] + w) continue; 其实有点没理解,应该是最短路。
// 3.2 记忆化:一个点只搜一次就可以了, 因为队列单调递增
// 注意下标别写错,调了好久发现是y写成了x。。。。
import java.util.*;
public class Main{
int maxN = 503;
char[][] graph = new char[maxN][maxN];
int[][] d = new int[maxN][maxN]; // 初始点到该点距离
boolean[][] visit = new boolean[maxN][maxN];
int[] dx = {-1, 1, 1 , -1};
int[] dy = {-1, -1, 1 , 1};
int[] mx = {-1, 0, 0, -1};
int[] my = {-1, -1, 0, 0};
char[] tc = {'\\', '/', '\\', '/'};
Deque<Integer> deque = new LinkedList<>();
void run(){
int t = jin.nextInt();
while(t-- != 0){
int r = jin.nextInt();
int c = jin.nextInt();
for (int i = 0 ; i < r ; i++) graph[i] = jin.next().toCharArray();
int res = solve( r, c, graph);
System.out.println(res == -1 ? "NO SOLUTION" : String.valueOf(res));
}
}
int zip(int x, int y) {return (x << 15) + y;}
int getX(int v){return v >> 15 ;}
int getY(int v){return v & ((1 << 15) -1 );}
int solve(int r, int c, char[][] graph){
for (int i = 0 ; i <= r ; i++) Arrays.fill(d[i], Integer.MAX_VALUE >> 1);
for (int i = 0 ; i <= r ; i++) Arrays.fill(visit[i], false);
deque.clear();
deque.addLast(0);
d[0][0] = 0;
while(!deque.isEmpty()){
int top = deque.pollFirst();
int x = getX(top);
int y = getY(top);
if (visit[x][y]) continue;
visit[x][y] = true;
for (int i = 0 ; i < 4 ; i++){
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || nx > r || ny < 0 || ny > c ) continue;
int gx = x + mx[i];
int gy = y + my[i];
if (gx <0 || gx >=r || gy < 0 || gy >= c) continue;
int w = graph[gx][gy] == tc[i] ? 0 : 1 ;
if (d[nx][ny] <= d[x][y] + w) continue;
d[nx][ny] = d[x][y] + w;
int v = zip(nx, ny);
if (w == 0) deque.addFirst(v);
else deque.addLast(v);
}
}
return d[r][c] == (Integer.MAX_VALUE >> 1) ? -1 : d[r][c];
}
Scanner jin = new Scanner(System.in);
public static void main(String[] args) throws Exception {new Main().run();}
}