#include "bits/stdc++.h"

using namespace std;
using ll = long long;
const double pi = acos(-1);
#define FOR(i,a,b) for (ll i=(a),__last_##i=(b);i<__last_##i;i++)
#define RFOR(i,a,b) for (ll i=(b)-1,__last_##i=(a);i>=__last_##i;i--)
#define REP(i,n) FOR(i,0,n)
#define RREP(i,n) RFOR(i,0,n)
#define __GET_MACRO3(_1, _2, _3, NAME, ...) NAME
#define rep(...) __GET_MACRO3(__VA_ARGS__, FOR, REP)(__VA_ARGS__)
#define rrep(...) __GET_MACRO3(__VA_ARGS__, RFOR, RREP)(__VA_ARGS__)
template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) {
	REP(i, v.size()) { if (i)os << " "; os << v[i]; }return os;
}
template<typename T> ostream& operator<<(ostream& os, const vector<vector<T>>& v) {
	REP(i, v.size()) { if (i)os << endl; os << v[i]; }return os;
}

const ll INF = 1LL << 60;
ll MOD = 1000000007;
ll _MOD = 1000000009;
double EPS = 1e-10;

#define int long long

const ll dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 };

inline void my_io() {

	std::ios::sync_with_stdio(false);

	std::cin.tie(0);

	cout << fixed << setprecision(10);

}

struct edge {

	int from, to, cap, rev;

};

vector<vector<edge>>g;//グラフの隣接リスト表現

vector<int>level;//sからの距離(辺何本分離れているか)

vector<int>iter;//どこまで調べ終わったか

int v, e;



void add_edge(int from, int to, int cap) {//from→to　容量capの辺をグラフに追加

	g[from].push_back(edge{ from,to,cap,(int)g[to].size() });

	g[to].push_back(edge{ to,from ,0,(int)g[from].size() - 1 });

}

void dinic_bfs(int s) {//sからの最短距離(辺何本分離れているか)をbfsで計算する

	fill(level.begin(), level.end(), -1);

	queue<int>que;

	level[s] = 0;

	que.push(s);

	while (!que.empty()) {

		int v = que.front();

		que.pop();

		for (int i = 0; i<g[v].size(); i++) {

			edge &e = g[v][i];

			if (e.cap > 0 && level[e.to] < 0) {

				level[e.to] = level[v] + 1;

				que.push(e.to);

			}

		}

	}

}

int dinic_dfs(int v, int t, int f) {//増加パスをdfsで探す

	if (v == t) {

		return f;

	}

	for (int &i = iter[v]; i < g[v].size(); i++) {//同じところを何度も調べないように枝刈りしている

		edge &e = g[v][i];

		if (e.cap > 0 && level[v] < level[e.to]) {

			int d = dinic_dfs(e.to, t, min(f, e.cap));

			if (d > 0) {

				e.cap -= d;

				g[e.to][e.rev].cap += d;

				return d;

			}

		}

	}

	return 0;

}

int max_flow(int s, int t) {

	int flow = 0;

	for (;;) {

		dinic_bfs(s);

		if (level[t] < 0) {

			return flow;

		}

		fill(iter.begin(), iter.end(), 0);

		int f;

		while ((f = dinic_dfs(s, t, numeric_limits<int>::max())) > 0) {

			flow += f;

		}

	}

}

signed main() {
	ll h, w;
	ll count = 0;
	pair<ll, ll> p1, p2;

	cin >> h >> w;

	vector<vector<char>> v1(h, vector<char>(w));
	vector<vector<ll>> v2(h, vector<ll>(w, INF));

	g.resize(h + w + 2);

	level.resize(h + w + 2);

	iter.resize(h + w + 2);

	REP(i, h) {
		REP(j, w) {
			cin >> v1[i][j];
			if (v1[i][j] == 'S') {
				add_edge(0, i + 1, INF);
				add_edge(0, j + h + 1, INF);
				p1 = make_pair(i, j);
			}
			else if (v1[i][j] == 'T') {
				add_edge(i + 1, h + w + 1, INF);
				add_edge(j + h + 1, h + w + 1, INF);
				p2 = make_pair(i, j);
			}
			else if (v1[i][j] == 'o') {
				add_edge(i + 1, j + h + 1, 1);
				add_edge(j + h + 1, i + 1, 1);
			}
		}
	}

	if (p1.first == p2.first || p1.second == p2.second) {
		cout << -1 << endl;
		return 0;
	}

	cout << max_flow(0, h + w + 1) << endl;

	return 0;

}

Measured memory_bytes: 2048