#include "bits/stdc++.h"
#include <sys/timeb.h>
#include <fstream>

using namespace std;

#define repl(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define rep(i,n) repl(i,0,n)
#define replrev(i,a,b) for(int i=(int)(b)-1;i>=(int)(a);i--)
#define reprev(i,n) replrev(i,0,n)
#define repi(itr,ds) for(auto itr = ds.begin(); itr != ds.end(); ++itr)
#define all(a) a.begin(),a.end()
#define mp make_pair
#define INF 2000000000
#define INFL 1000000000000000000LL
#define EPS 1e-9
#define MOD 1000000007
#define PI 3.1415926536
#define RMAX 4294967295

typedef long long ll;
typedef pair<int, int> P;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<bool> vb;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<double> vd;
typedef vector<P> vP;
typedef vector<vector<int> > vvi;
typedef vector<vector<bool> > vvb;
typedef vector<vector<ll> > vvll;
typedef vector<vector<char> > vvc;
typedef vector<vector<double> > vvd;
typedef vector<vector<P> > vvP;
typedef priority_queue<int, vector<int>, greater<int> > pqli;
typedef priority_queue<ll, vector<ll>, greater<ll> > pqlll;
typedef priority_queue<P, vector<P>, greater<P> > pqlP;
typedef pair<int, pair<int, int> > Edge;
typedef vector<Edge> vE;
typedef priority_queue<Edge, vector<Edge>, greater<Edge> > pqlE;

//to:行き先,cap:容量,rev:逆(G[e.to][e.rev]で逆辺の構造体にアクセスできる。)
struct edge {
	int to, cap, rev;
};

vector<edge> G[220];
bool used[220];

//辺を追加。revは,相互参照できるようにしている。sizeで実現しているが、別のルールを用いても良い(i.e ハッシュ)。逆辺の逆辺は通常の辺である。
void add_edge(int from, int to, int cap)
{
	G[from].push_back(edge{ to, cap, (int)G[to].size() });
	G[to].push_back(edge{ from, 0, (int)G[from].size() - 1 });
}

//sからtへ移動可能ならそのルートの最大流量を返し、不可能なら0を返す。
int dfs(int v, int t, int f)
{
	if (v == t) return f;
	used[v] = true;
	rep(i, G[v].size()) {
		edge &e = G[v][i];
		if (!used[e.to] && e.cap>0) {
			int d = 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;
}

//sからtへの最大流量を返す。
int
max_flow(int s, int t)
{
	int flow = 0;
	while (true) {
		memset(used, 0, sizeof(used));
		int f = dfs(s, t, INF);
		if (f == 0) {
			return flow;
		}
		flow += f;
	}
}

int main() {
	int H, W;
	cin >> H >> W;
	vP e;
	P s, t;
	rep(i, H) {
		string str;
		cin >> str;
		rep(j, W) {
			if (str[j] == 'o') {
				e.push_back(mp(i, j));
			}
			else if (str[j] == 'S') {
				s = mp(i, j);
			}
			else if (str[j] == 'T') {
				t = mp(i, j);
			}
		}
	}
	if (s.first == t.first || s.second == t.second) {
		cout << -1 << endl;
		return 0;
	}
	rep(i, e.size()) {
		if (e[i].first == s.first&&e[i].second == t.second) {
			add_edge(0, W + H + 1, 1);
			add_edge(W + H + 1, 0, 1);
		}
		else if (e[i].first == t.first&&e[i].second == s.second) {
			add_edge(0, W + H + 1, 1);
			add_edge(W + H + 1, 0, 1);
		}
		else if (e[i].first == s.first) {
			add_edge(0, e[i].second + H + 1, 1);
			add_edge(e[i].second + H + 1, 0, 1);
		}
		else if (e[i].second == s.second) {
			add_edge(0, e[i].first + 1, 1);
			add_edge(e[i].first + 1, 0, 1);
		}
		else if (e[i].first == t.first) {
			add_edge(H + W + 1, e[i].second + H + 1, 1);
			add_edge(e[i].second + H + 1, H + W + 1, 1);
		}
		else if (e[i].second == t.second) {
			add_edge(H + W + 1, e[i].first + 1, 1);
			add_edge(e[i].first + 1, H + W + 1, 1);
		}
		else {
			add_edge(e[i].first + 1, e[i].second + H + 1, 1);
			add_edge(e[i].second + H + 1, e[i].first + 1, 1);
		}
	}
	cout << max_flow(0, H + W + 1) << endl;

	return 0;
}

Measured memory_bytes: 1024