#include <bits/stdc++.h>

#define rep(i,n) for(int i=0; i<(n); i++)
#define reps(i,x,n) for(int i=x; i<(n); i++)
#define rrep(i,n) for(int i=(n)-1; i>=0; i--)
#define all(X) (X).begin(),(X).end()
#define X first
#define Y second
#define pb push_back
#define eb emplace_back

using namespace std;
typedef long long int ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef vector<int> vi;

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }

template<class A, size_t N, class T> void Fill(A (&a)[N], const T &v){ fill( (T*)a, (T*)(a+N), v ); }

const ll INF = 1e5;

// 最大流を求める(Dinic法)
class Flow{
	public:
		int N;	// 頂点数
		vector<vi> F, C, edge;	// F:残余グラフ C:初期容量 edge:隣接する頂点

		vi itr, lv;	// itr:調べ終わったかどうか  lv:Sからの距離

		// コンストラクタ n:頂点数
		Flow(int n): N(n), F(n,vi(n)), C(n,vi(n)), edge(n) {}

		// f->tにコストcの辺を追加する(同じf->tに対して何度も追加することも可能)
		void addEdge(int f, int t, int c){
			//cout << "add : " << f << " - " << t << endl;
			F[f][t] = C[f][t] = c;
			edge[f].push_back(t);
			edge[t].push_back(f);
		}

		// sからの最短距離を求める。これを実行するとDFSでは最短経路の中から探索する
		int bfs(int S, int T){
			lv.assign(N, 0);
			queue<int> q;
			q.push(S);
			lv[S] = 1;
			while( !q.empty() ){
				int n = q.front(); q.pop();
				for(auto v: edge[n]) if( !lv[v] && F[n][v] ){
					lv[v] = lv[n] + 1;
					q.push(v);
				}
			}
			return lv[T];
		}

		// 増加パスをDFSで探す
		int dfs(int n, int c, int T){
			if( n == T ) return c;
			for(;itr[n] < edge[n].size(); ++itr[n]){
				int v = edge[n][itr[n]];
				if( F[n][v] && lv[v] > lv[n] ){
					int f = dfs(v, min(c, F[n][v]), T);
					F[n][v] -= f;
					F[v][n] += f;
					if(f) return f;
				}
			}
			return 0;
		}

		// 流す。最大流を求める(現在の状態からいくら流れたかが返ってくる)
		int maxFlow(int S, int T){
			if( S == T ) return INF;
			int ret = 0;
			while( bfs(S,T) ){
				itr.assign(N,0);
				for(int f; f=dfs(S, INF, T);) ret += f;
			}
			return ret;
		}

		// 辺に流れている流量を取得する
		int flow(int f, int t){ return C[f][t] - F[f][t]; }

		// 隣接する辺の流量の合計を取得する。n=S,T以外の場合は、出た値を1/2倍したものがその点の流量
		int flow(int n){
			int ret=0;
			for(int v: edge[n]) ret += abs( flow(n,v) );
			return ret;
		}

		// グラフを初期値に戻す
		void reset(){ rep(i,N) rep(j,N) F[i][j] = C[i][j]; }
};

int main(){
	//ios_base::sync_with_stdio(0);
	int H, W, ans=0;
	string s[105];

	cin >> H >> W;
	rep(i,H) cin >> s[i];

	vector<pii> v;
	int start, goal;
	rep(i,H) rep(j,W){
		if( s[i][j] == 'o' ){
			v.emplace_back(i,j);
		}
		if( s[i][j] == 'S' ){
			start = v.size();
			v.emplace_back(i,j);
		}
		if( s[i][j] == 'T' ){
			goal = v.size();
			v.emplace_back(i,j);
		}
	}

	Flow fl(210);
	//int OUT = 102;
	int IN_H = 5;
	int IN_W = 108;
	rep(i,v.size()){
		//cout << "addEdge " << v[i].X << " " << v[i].Y << endl;
		//fl.addEdge( IN_H + v[i].X, i, INF);
		//fl.addEdge( IN_W + v[i].Y, i, INF);
		//fl.addEdge( i, IN_H + v[i].X, INF);
		//fl.addEdge( i, IN_W + v[i].Y, INF);
		if( i != start && i != goal ){
			fl.addEdge( IN_H + v[i].X, IN_W + v[i].Y, 1 );
			fl.addEdge( IN_W + v[i].Y, IN_H + v[i].X, 1 );
		}
		//fl.addEdge( IN_H + v[i].X, OUT + i, INF);
		//fl.addEdge( IN_W + v[i].Y, OUT + i, INF);
		//fl.addEdge( OUT + i, IN_H + v[i].X, INF);
		//fl.addEdge( OUT + i, IN_W + v[i].Y, INF);
	}
	fl.addEdge( 0, IN_H + v[start].X, INF );
	fl.addEdge( 0, IN_W + v[start].Y, INF );
	fl.addEdge( IN_H + v[goal].X, 1, INF );
	fl.addEdge( IN_W + v[goal].Y, 1, INF );

	ans = fl.maxFlow(0, 1);

	if( ans >= INF ) ans = -1;
	cout << ans << endl;

	return 0;
}


Measured memory_bytes: 896