// Arup Guha
// 2/28/2013 (finished 3/4/2013)
// Solution to 2013 Mercer Problem #10: Rock Candy

import java.util.*;

public class prob10 {

	public final static char BARRIER = '#';
	public final static char TOBY = 'T';
	public final static char OPEN = '.';
	public final static char ROCK = 'R';
	public final static int IMPOSSIBLE = -1;
	public final static int[][] delta = {{-1,0}, {0,1}, {1,0}, {0, -1}};

	private char[][] grid;
	private int numRocks;
	private int curX;
	private int curY;
	private int[][] rockList;
	private int numRows;
	private int numCols;

	public prob10(char[][] input) {

		numRows = input.length;
		numCols = input[0].length;
		grid = new char[numRows][numCols];
		numRocks = 0;

		// Copy unchangeable part of the grid.
		for (int i=0; i<numRows; i++) {
			for (int j=0; j<numCols; j++) {

				// Found the starting spot.
				if (input[i][j] == TOBY) {
					grid[i][j] = OPEN;
					curX = i;
					curY = j;
				}

				// Here we store an open, because rocks will be stored elsewhere.
				else if (input[i][j] == ROCK) {
					grid[i][j] = OPEN;
					numRocks++;
				}

				else
					grid[i][j] = input[i][j];
			}
		}

		// Fill in the rocks.
		rockList = new int[numRocks][2];
		int rockIndex = 0;
		for (int i=0; i<numRows; i++) {
			for (int j=0; j<numCols; j++) {

				if (input[i][j] == ROCK) {
					rockList[rockIndex][0] = i;
					rockList[rockIndex][1] = j;
					rockIndex++;
				}
			}

		}
	}

	public static void main(String[] args) {

		Scanner stdin = new Scanner(System.in);
		int numCases = stdin.nextInt();

		// Go through all cases.
		for (int loop=1; loop<=numCases; loop++) {

			int numRows = stdin.nextInt();
			int numCols = stdin.nextInt();
			char[][] grid = new char[numRows][];
			for (int i=0; i < numRows; i++) {

				/*** Note: This line here expects the number of grid characters on each row
				 *         to equal numCols. ***/
				String line = stdin.next();
				grid[i] = line.toCharArray();
			}

			// Create my rock candy object.
			prob10 myCandy = new prob10(grid);
			solution best = myCandy.solve();
			System.out.println("Mine #"+loop+": "+best.getRocks()+" "+best.getMoves());
			System.out.println();
		}

	}

	public solution solve() {

		// Add in our initial state to our queue for searching.
		PriorityQueue<solution> q = new PriorityQueue<solution>();
		HashMap<Integer,Integer> used = new HashMap<Integer,Integer>();
		int curState = ((curX*numCols + curY) << numRocks) + (1 << numRocks) - 1;
		solution start = new solution(0, 0, numRocks, curState, curX, curY);
		solution best = null;
		q.offer(start);
		used.put(curState,0);

		// Search whole space.
		while (q.size() > 0) {

			// Get the next item from the queue.
			solution temp = q.poll();

			// Update best, if necessary.
			if (best == null)
				best = temp;
			else if (temp.getRocks() > best.getRocks())
				best = temp;
			else if (temp.getRocks() == best.getRocks() && temp.getMoves() < best.getMoves())
				best = temp;

			// Calculate all the next possible states from here.
			ArrayList<solution> next = getNext(temp);

			// Go through next states, adding to queue, if necessary.
			for (int i=0; i<next.size(); i++) {

				// Never been here.
				if (!used.containsKey(next.get(i).getMask())) {
					q.offer(next.get(i));
					used.put(next.get(i).getMask(), next.get(i).getMoves());
				}

				// Been here, but this solution is better.
				else if (used.containsKey(next.get(i).getMask()) && next.get(i).getMoves() < used.get(next.get(i).getMask()) ) {
					q.offer(next.get(i));
					used.put(next.get(i).getMask(), next.get(i).getMoves());
				}
			}
		}

		return best;
	}

	// Return the next possible states after knocking off one more rock.
	public ArrayList<solution> getNext(solution best) {

		ArrayList<solution> list = new ArrayList<solution>();

		int[][] distances = getDistances(best);

		// Try traveling to each existing rock.
		int subset = best.getMask() & ((1 << numRocks) - 1);
		int savesubset = subset;
		for (int item=0; item<numRocks; item++) {

			// The rock exists.
			if ((subset & 1) == 1) {

				// Try going to each orientation of pushing the rock.
				for (int i=0; i<delta.length; i++) {

					int newX = rockList[item][0] + delta[i][0];
					int newY = rockList[item][1] + delta[i][1];

					if (newX < 0 || newX >= numRows || newY < 0 || newY >= numCols) continue;

					// We can get here.
					if (distances[newX][newY] != IMPOSSIBLE) {

						// We can push the rock off, so add this to our list.
						if (okay(newX, newY, rockList[item][0], rockList[item][1], savesubset)) {
							int newstate = ((newX*numCols + newY) << numRocks) + savesubset - (1 << item);
							solution next = new solution(best.getRocks()+1, best.getMoves()+distances[newX][newY]+1, best.getTotalRocks(), newstate, newX, newY);
							list.add(next);
						}
					}
				}
			}

			subset = subset >> 1;
		}

		return list;
	}

	// Get the best distances building off the solution sol.
	public int[][] getDistances(solution sol) {

		// Will store shortest distances.
		int[][] ans = new int[numRows][numCols];

		// -1 indicates haven't been there yet.
		for (int i=0; i<numRows; i++)
			Arrays.fill(ans[i],IMPOSSIBLE);

		// Temp grid for this calcuation.
		char[][] tempG = new char[numRows][numCols];
		for (int i=0; i<numRows; i++)
			for (int j=0; j<numCols; j++)
				tempG[i][j] = grid[i][j];

		// Place the rocks that need to be placed.
		int tempMask = sol.getMask();
		for (int i=0; i<numRocks; i++) {
			if ((tempMask & 1) == 1)
				tempG[rockList[i][0]][rockList[i][1]] = BARRIER;
			tempMask = tempMask >> 1;
		}

		// Now, we can do a BFS to fill in these distances.
		LinkedList<Integer> q = new LinkedList<Integer>();
		q.offer(sol.getCurX()*numCols+sol.getCurY());
		ans[sol.getCurX()][sol.getCurY()] = 0;

		while (q.size() > 0) {

			// Get next move and store it in our answer grid.
			int next = q.poll();
			if (next < 0) continue;
			int nextR = next/numCols;
			int nextC = next%numCols;
			int moves = ans[nextR][nextC];

			// Try adding moves to each direction.

			if (nextR > 0 && ans[nextR-1][nextC] == IMPOSSIBLE && tempG[nextR-1][nextC] == OPEN) {
				q.offer((nextR-1)*numCols+nextC);
				ans[nextR-1][nextC] = moves+1;
			}

			if (nextR < numRows-1 && ans[nextR+1][nextC] == IMPOSSIBLE && tempG[nextR+1][nextC] == OPEN) {
				q.offer((nextR+1)*numCols+nextC);
				ans[nextR+1][nextC] = moves+1;
			}

			if (nextC > 0 && ans[nextR][nextC-1] == IMPOSSIBLE && tempG[nextR][nextC-1] == OPEN) {
				q.offer(nextR*numCols + nextC-1);
				ans[nextR][nextC-1] = moves+1;
			}

			if (nextC < numCols-1 && ans[nextR][nextC+1] == IMPOSSIBLE && tempG[nextR][nextC+1] == OPEN) {
				q.offer(nextR*numCols + nextC+1);
				ans[nextR][nextC+1] = moves+1;
			}

		}

		return ans;
	}

	// Returns true iff we can push the rock at (startX, startY) towards (nextX, nextY) and
	// encounter no barriers. Subset stores the subset of rocks still on the board.
	public boolean okay(int startX, int startY, int nextX, int nextY, int subset) {

		int deltaX = nextX - startX;
		int deltaY = nextY - startY;

		// Check if any square on the push path is blocked or has a rock.
		for (int i=nextX+deltaX, j=nextY+deltaY; i>=0 && j>=0 && i<numRows && j<numCols; i+=deltaX, j+=deltaY) {

			// Easy to look for a barrier.
			if (grid[i][j] == BARRIER)
				return false;

			// Check if any of the rocks that exist are on square [i,j].
			int tempsub = subset;
			for (int k=0; k<rockList.length; k++) {
				if ((tempsub & 1) == 1 && rockList[k][0] == i && rockList[k][1] == j)
					return false;
				tempsub = tempsub >> 1;
			}
		}

		return true;
	}

}

class solution implements Comparable<solution> {

	private int numRocks;
	private int mask;
	private int rocksCleared;
	private int numMoves;
	private int tobyX;
	private int tobyY;

	public solution(int rocks, int moves, int totalRocks, int state, int startX, int startY) {
		rocksCleared = rocks;
		numMoves = moves;
		numRocks = totalRocks;
		mask = state;
		tobyX = startX;
		tobyY = startY;
	}

	public int compareTo(solution other) {
		if (this.rocksCleared != other.rocksCleared)
			return this.rocksCleared - other.rocksCleared;

		// Sort fewer moves first.
		return this.numMoves - other.numMoves;
	}

	public int getRocks() {
		return rocksCleared;
	}

	public int getMoves() {
		return numMoves;
	}

	public int getMask() {
		return mask;
	}

	public int getCurX() {
		return tobyX;
	}

	public int getCurY() {
		return tobyY;
	}

	public int getTotalRocks() {
		return numRocks;
	}
}