#include <bits/stdc++.h>
#define pb emplace_back
#define pii pair<int, int>
#define x first
#define y second
#define S first
#define T second
using namespace std;
mt19937_64 rang(chrono::high_resolution_clock::now().time_since_epoch().count());
int rng(int l) { uniform_int_distribution<int> uid(0, l - 1); return uid(rang); }
typedef long long fType;
struct edge { unsigned from, to; fType cap, flow; edge(unsigned from, unsigned to, fType cap, fType flow = 0) : from(from), to(to), cap(cap), flow(flow) {} };
struct PushRelabel
{
	unsigned N;
	vector<edge> E;
	vector<vector<unsigned> > G;
	vector<unsigned> h, count;
	vector<bool> inQ;
	vector<fType> excess;
	queue<unsigned> Q;
	PushRelabel(unsigned N) : N(N), count(N << 1), G(N), h(N), inQ(N), excess(N) {}

	void pb(unsigned from, unsigned to, fType cap) {
		G[from].push_back(E.size());
		E.push_back(edge(from, to, cap));
		G[to].push_back(E.size());
		E.push_back(edge(to, from, 0));
	}

	void enQueue(unsigned u) {
		if (!inQ[u] && excess[u] > 0) Q.push(u), inQ[u] = true;
	}

	void Push(unsigned edgeIdx) {
		edge & e = E[edgeIdx];
		fType toPush = min<fType>(e.cap - e.flow, excess[e.from]);
		if (toPush > static_cast<fType>(0) && h[e.from] > h[e.to]) {
			e.flow += toPush;
			excess[e.to] += toPush;
			excess[e.from] -= toPush;
			E[edgeIdx ^ 1].flow -= toPush;
			enQueue(e.to);
		}
	}

	void Relabel(unsigned u) {
		count[h[u]] -= 1; h[u] = (N << 1) - 2;
		for (unsigned i : G[u]) {
			edge &e = E[i];
			if (e.cap > e.flow) h[u] = min(h[u], h[e.to]);
		}
		count[++h[u]] += 1;
	}

	void gapRelabel(unsigned height) {
		for (unsigned u = 0; u < N; ++u)
			if (h[u] >= height && h[u] < N) {
				count[h[u]]--;
				count[h[u] = N]++;
				enQueue(u);
			}
	}

	void Discharge(unsigned u) {
		for (unsigned i = 0; excess[u] > 0 && i < G[u].size(); ++i) Push(G[u][i]);
		if (excess[u] > 0) {
			if (h[u] < N && count[h[u]] < 2) gapRelabel(h[u]);
			else Relabel(u);
		}
		else if (!Q.empty()) {
			Q.pop();
			inQ[u] = false;
		}
	}

	fType getFlow(unsigned src, unsigned snk) {
		h[src] = N; inQ[src] = inQ[snk] = true;
		count[0] = N - (count[N] = 1);
		for (unsigned i : G[src]) {
			excess[src] += E[i].cap;
			Push(i);
		}
		while (!Q.empty())
			Discharge(Q.front());
		return excess[snk];
	}
};



int32_t main() {
	ios::sync_with_stdio(false); cin.tie(NULL); cout.precision(10); srand(chrono::high_resolution_clock::now().time_since_epoch().count());
	int n; cin >> n;
	int m; cin >> m;
	vector<string> s(n); for (int o = 0; o < n; o++) { cin >> s[o]; }
	std::map<pii, pii> MapOfLeaves;
	int cn = 2;
	int sx, sy, tx, ty;
	for (int i = 0; i < n; ++i)
		for (int j = 0; j < m; ++j)
			if (s[i][j] == 'S')
				sx = i, sy = j;
			else if (s[i][j] == 'T')
				tx = i, ty = j;
	for (int i = 0; i < n; ++i)
		for (int j = 0; j < m; ++j)
			if (s[i][j] == 'o')
				MapOfLeaves[ {i, j}] = {cn, cn + 1}, cn += 2;
	if (sx == tx || sy == ty) {
		cout << -1; 
		return 0;
	}
	PushRelabel g(cn);
	for (int i = 2; i < cn; i += 2)
		g.pb(i, i + 1, 1);
	for (int i = 0; i < n; ++i)
		if (s[i][sy] == 'o')
			g.pb(0, MapOfLeaves[ {i, sy}].S, 1000000);
	for (int i = 0; i < m; ++i)
		if (s[sx][i] == 'o')
			g.pb(0, MapOfLeaves[ {sx, i}].S, 1000000);
	for (int i = 0; i < n; ++i)
		if (s[i][ty] == 'o')
			g.pb(MapOfLeaves[ {i, ty}].T, 1, 1000000);
	for (int i = 0; i < m; ++i)
		if (s[tx][i] == 'o')
			g.pb(MapOfLeaves[ {tx, i}].T, 1, 1000000);
	for (auto p : MapOfLeaves) {
		auto c = p.x;
		auto node = p.y;
		for (int i = 0; i < n; ++i)
			if (s[i][c.y] == 'o' && i != c.x)
				g.pb(node.T, MapOfLeaves[{i, c.y}].S, 1000000);
		for (int i = 0; i < m; ++i)
			if (s[c.x][i] == 'o' && i != c.y)
				g.pb(MapOfLeaves[{c.x, i}].T, node.S, 1000000);
	}
	cout << g.getFlow(0, 1);
}

Measured memory_bytes: 116252