#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <functional>
#include <cmath>
#include <set>
#include <queue>
#include <deque>
#include <vector>
#include <climits>
#include <sstream>
#include <iomanip>
#include <map>
#include <stack>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;

struct EdgeMF
{
	int to;
	ll capacity;
	int reverse;
};

void addEdgeForFlow(vector<vector<EdgeMF>>& G, int from, int to, ll capacity, ll reverseCapacity)
{
	G[from].push_back({ to, capacity, (int)G[to].size() });
	G[to].push_back({ from, reverseCapacity, (int)G[from].size() - 1 });
}

void bfsForFlowD(vector<vector<EdgeMF>>& G, vector<int>& distance, int s)
{
	queue<int> q;
	distance[s] = 0;
	q.push(s);
	while (!q.empty())
	{
		auto v = q.front();
		q.pop();
		for (auto& e : G[v])
		{
			if (e.capacity > 0 && distance[e.to] < 0)
			{
				distance[e.to] = distance[v] + 1;
				q.push(e.to);
			}
		}
	}
}

ll dfsForFlowD(vector<vector<EdgeMF>>& G, vector<int>& distance, vector<int>& researched, int u, int t, ll f)
{
	if (u == t)
	{
		return f;
	}

	for (auto& i = researched[u]; i < (int)G[u].size(); ++i)
	{
		auto& e = G[u][i];
		if (e.capacity <= 0 || distance[u] >= distance[e.to])
		{
			continue;
		}

		auto d = dfsForFlowD(G, distance, researched, e.to, t, min(f, e.capacity));
		if (d > 0)
		{
			e.capacity -= d;
			G[e.to][e.reverse].capacity += d;
			return d;
		}
	}

	return 0;
}

ll calcMaxFlowD(vector<vector<EdgeMF>>& G, int s, int t)
{
	auto f = 0ll;
	while (true)
	{
		vector<int> distance((int)G.size(), -1);
		bfsForFlowD(G, distance, s);
		if (distance[t] < 0)
		{
			break;
		}
		vector<int> researched((int)G.size());
		while (true)
		{
			auto d = dfsForFlowD(G, distance, researched, s, t, LLONG_MAX);
			if (d <= 0)
			{
				break;
			}
			f += d;
		}
	}

	return f;
}

int main()
{
	int s = -1;
	int t = -1;
	int H, W;
	cin >> H >> W;

	vector<string> a(H);
	for (auto i = 0; i < H; ++i)
	{
		cin >> a[i];

		for (auto j = 0; j < W; ++j)
		{
			auto from = i * W + j;
			switch (a[i][j])
			{
			case 'S':
				s = from;
				break;

			case 'T':
				t = from;
				break;
			}
		}
	}

	vector<vector<EdgeMF>> G(2 * H * W);
	int offset = H * W;
	for (auto i = 0; i < H; ++i)
	{
		for (auto j = 0; j < W; ++j)
		{
			if (a[i][j] == '.')
			{
				continue;
			}

			auto from = i * W + j;
			if (from != s && from != t)
			{
				addEdgeForFlow(G, from, from + offset, 0, 1);
			}

			ll capacity = 1;
			ll reverseCapacity = 1;
			if (from == s)
			{
				reverseCapacity = 0;
			}
			else if (from == t)
			{
				capacity = 0;
			}

			for (auto k = j + 1; k < W; ++k)
			{
				if (a[i][k] == '.')
				{
					continue;
				}
				auto to = i * W + k;
				auto tempC = capacity;
				auto tempR = reverseCapacity;
				if (to == s)
				{
					tempC = 0;
				}
				else if (to == t)
				{
					tempR = 0;
				}

				addEdgeForFlow(G, from, to + offset, tempC, 0);
				addEdgeForFlow(G, to, from + offset, tempR, 0);
			}
			for (auto k = i + 1; k < H; ++k)
			{
				if (a[k][j] == '.')
				{
					continue;
				}
				auto to = k * W + j;
				auto tempC = capacity;
				auto tempR = reverseCapacity;
				if (to == s)
				{
					tempC = 0;
				}
				else if (to == t)
				{
					tempR = 0;
				}

				addEdgeForFlow(G, from, to + offset, tempC, 0);
				addEdgeForFlow(G, to, from + offset, tempR, 0);
			}
		}
	}

	if (s % W == t % W
		|| s / W == t / W)
	{
		cout << -1 << endl;
	}
	else
	{
		cout << calcMaxFlowD(G, s, t + offset) << endl;
	}

	return 0;
}

Measured memory_bytes: 127640