//marico el que lo lea
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <stdlib.h>
#include <assert.h>
using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> ii;

void fastIO() {
	std::ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
}

#define FOR(i,f,t) for(int i=f; i<(int)t; i++)
#define FORR(i,f,t) for(int i=f; i>(int)t; i--)
#define FORE(i,c) for(auto i = (c).begin(); i != (c).end(); i++)
#define pb push_back
#define all(obj) obj.begin(), obj.end()
#define ms(obj, val) memset(obj, val, sizeof(obj))
#define ms2(obj, val, sz) memset(obj, val, sizeof(obj[0])*sz)

#define fst first
#define snd second

template<typename T, typename U> inline void mnze(T &x, U y) { if(y < x) x = y; }
template<typename T, typename U> inline void mxze(T &x, U y) { if(x < y) x = y; }

void _scan( int &x ) { scanf("%d",&x); }
void _scan( long long &x ) { scanf("%lld",&x); }
void _scan( double &x ) { scanf("%lf",&x); }
void _scan( char &x ) { scanf(" %c",&x); }
void _scan( char *x ) { scanf("%s",x); }
void scan() {}
template<typename T, typename... U>
void scan( T& head, U&... tail ) { _scan(head); scan(tail...);}

template<typename T> void _dbg(const char* sdbg, T h) { cerr<<sdbg<<"="<<h<<"\n"; }
template<typename T, typename... U> void _dbg(const char* sdbg, T h, U... t) {
	while(*sdbg != ',')cerr<<*sdbg++; cerr<<"="<<h<<","; _dbg(sdbg+1, t...);
}

#ifdef LOCAL
#define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#define debugv(x) {{cerr <<#x <<" = "; FORE(_i, (x)) cerr <<*_i <<", "; cerr <<"\n"; }}
#define debuga(x, sz) {{cerr <<#x <<" = "; FOR(_i, 0, sz) cerr << x[_i] <<", "; cerr <<"\n"; }}
#else
#define debug(...) (__VA_ARGS__)
#define debugv(x)
#define debuga(x, sz)
#define cerr if(0)cout
#endif

///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////

const int MAXN = 2e4+5;
const ll INF = 1LL<<61;
 
struct edge {
	int a, b;
	ll cap;
};
 
int N, s, t, d[MAXN], ptr[MAXN];
vector<edge> e;
vector<int> G[MAXN];
 
void add_edge(int a, int b, ll cap) {
	edge e1 = { a, b, cap};
	edge e2 = { b, a, 0};
	G[a].pb((int)e.size());
	e.pb(e1);
	G[b].pb((int) e.size());
	e.pb(e2);
}
 
bool bfs() {
	queue<int> q;
	q.push(s);
	memset (d, -1, (N+1) * sizeof d[0]);
	d[s] = 0;
	while(!q.empty() && d[t] == -1) {
		int v = q.front(); q.pop();
		FOR(i,0,G[v].size()){
			int id = G[v][i], to = e[id].b;
			if(d[to] == -1 && e[id].cap){
				q.push(to);
				d[to] = d[v] + 1;
			}
		}
	}
	return d[t] != -1;
}
 
ll dfs(int v, ll flow){
	if(!flow) return 0;
	if (v == t)  return flow;
	for (; ptr[v]<(int)G[v].size(); ++ptr[v]) {
		int id = G[v][ptr[v]], to = e[id].b;
		if(d[to] != d[v]+1) continue;
		int pushed = dfs(to, min(flow, (ll) e[id].cap));
		if(pushed){
			e[id].cap -= pushed;
			e[id^1].cap += pushed;
			return pushed;
		}
	}
	return 0;
}
 
ll dinic() {
	ll flow = 0;
	while(true){
		if (!bfs())  break;
		memset (ptr, 0, (N+1) * sizeof ptr[0]);
		while (ll pushed = dfs(s, INF))
			flow += pushed;
	}
	return flow;
}

#define in(v) (2*v)
#define out(v) (2*v+1)

const int MAX = 105;

int R, C;
int id[MAX][MAX], n=2;

int main(){
	scan(R,C);
	s=0, t=1;
	int sr, sc, tr, tc;
	ms(id,-1);
	FOR(r,0,R){
		char tmp[105]; scan(tmp);
		FOR(c,0,C){
			if(tmp[c]=='S'){
				sr=r; sc=c;
				id[r][c] = s;
			}
			if(tmp[c]=='T'){
				tr=r; tc=c;
				id[r][c] = t;
			}
			if(tmp[c]=='o'){
				id[r][c] = n++;
			}
		}
	}
	if(sr == tr || sc == tc){
		printf("-1\n");
		return 0;
	}
	N=2*n;
	s=out(s); t=in(t);
	FOR(i,0,n){
		add_edge(in(i),out(i),1);
	}
	FOR(r,0,R) FOR(c,0,C){
		if(id[r][c]==-1) continue;
		FOR(nr,0,R) if(nr!=r && id[nr][c] != -1)
			add_edge(out(id[r][c]), in(id[nr][c]), INF);
		FOR(nc,0,C) if(nc!=c && id[r][nc] != -1)
			add_edge(out(id[r][c]), in(id[r][nc]), INF);
	}
	printf("%lld\n",dinic());
}

Measured memory_bytes: 85724