#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define mp make_pair
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef complex<double> point;
#define xx real()
#define yy imag()

#define REP(i, a, b) for(int i = (a); i < (int)(b); i++)
#define REPN(i, a, b) for(int i = (a); i <= (int)(b); i++)
#define FA(it, x) for(__typeof((x).begin()) it = (x).begin(); it != (x).end(); it++)
#define SZ(x) (int)(x).size()
#define BE(x) (x).begin(), (x).end()
#define SORT(x) sort(BE(x))
#define _1 first
#define _2 second

#define x1 gray_cat_x1
#define y1 gray_cat_y1

template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }

#define file "I1"

const double EPS = 1e-9;
const double PI = acos(-1.);
const int INF = 1e9;
const ll MOD = 1e9 + 7;

const int MAXCNT = 105;
const int MAXN = 2e2 + 5;
const int LIM = 1e4;

struct edge{
	int s, to, cap, flow;
};

struct graph {
	// Number of vertices and edges
	int n;
	
	// Edges
	vector<edge> ee;
	
	// Graph
	vi g[MAXN];
	
	// start, finish
	int s, t;
	
	// Distance for BFS
	int dis[MAXN];
	
	// Queue for BFS
	int qq[MAXN];
	
	// Ptr for DFS
	int ptr[MAXN];
	
	// Adding edge
	void add_edge(int a, int b, int cap){		
		edge e1 = { a, b, cap, 0 };
		edge e2 = { b, a, 0, 0 };
		g[a].pb(SZ(ee));
		ee.pb(e1);
		g[b].pb(SZ(ee));
		ee.pb(e2);
	}	
	
	// BFS for Dinic
	bool bfs(){
		// Init
		int qh = 0, qt = 0;
		qq[qt++] = s;
		REPN(i, 1, n){
			dis[i] = -1;
		}
		dis[s] = 0;
		
		// Go
		while (qh < qt) {
			int v = qq[qh++];
			REP(i, 0, SZ(g[v])){
				int ind = g[v][i];
				int to = ee[ind].to;
				if (dis[to] == -1 && ee[ind].flow < ee[ind].cap) {
					qq[qt++] = to;
					dis[to] = dis[v] + 1;
				}
			}
		}
		
		return dis[t] != -1;
	}
	
	// DFS for Dinic
	int dfs (int v, int cur_flow){
		if (!cur_flow){
			return 0;
		}
		if (v == t) {
			return cur_flow;
		}
		for (; ptr[v] < SZ(g[v]); ++ptr[v]) {
			int ind = g[v][ptr[v]];
			int to = ee[ind].to;
			if (dis[to] != dis[v] + 1) {
				continue;
			}
			int pushed = dfs(to, min(cur_flow, ee[ind].cap - ee[ind].flow));
			if (pushed) {
				ee[ind].flow += pushed;
				ee[ind ^ 1].flow -= pushed;
				return pushed;
			}
		}
		return 0;
	}
	
	// Dinic
	int dinic(int _s, int _t) {
		// Init
		s = _s, t = _t;
		REP(i, 0, SZ(ee)){
			ee[i].flow = 0;
		}
		int result = 0;
		
		// Go
		while(1) {			
			if (!bfs()) { 
				break;
			}
			REPN(i, 1, n){
				ptr[i] = 0;
			}
			while (int pushed = dfs(s, INF)) {
				result += pushed;
				/*if (result >= LIM) {
					return result;
				}*/
			}
		}
		
		return result;
	}
} gg;

char grid[MAXCNT][MAXCNT];

int ind_row[MAXCNT], ind_column[MAXCNT];

void solve(){
	int h, w;
	scanf("%d%d", &h, &w);
	REP(i, 0, h) {
		scanf("%s", &grid[i][0]);
		ind_row[i] = i + 1;
	}
	REP(j, 0, w) {
		ind_column[j] = 1 + h + j;
	}
	int si, sj, ti, tj;
	gg.n = 1 + h + w + 2;
	int s = gg.n - 1, t = gg.n;
	REP(i, 0, h) {
		REP(j, 0, w) {
			if (grid[i][j] == 'S') {
				si = i;
				sj = j;
				gg.add_edge(s, ind_row[i], LIM);
				gg.add_edge(s, ind_column[j], LIM);
			} else if (grid[i][j] == 'T') {
				ti = i;
				tj = j;
				gg.add_edge(ind_row[i], t, LIM);
				gg.add_edge(ind_column[j], t, LIM);
			} else if (grid[i][j] == 'o') {
				gg.add_edge(ind_row[i], ind_column[j], 1);
				gg.add_edge(ind_column[j], ind_row[i], 1);
			}
		}
	}
	if (si == ti || sj == tj) {
		printf("-1\n");
		return;
	}
	int maxflow = gg.dinic(s, t);
	/*if (maxflow >= LIM) {
		maxflow = -1;
	}*/
	printf("%d\n", maxflow);
}   

int main(){

    //freopen(file".in", "r", stdin); freopen(file".out", "w", stdout);
    int t = 1;
    //cin >> t;
    while(t--){
        solve();    
    }
}


Measured memory_bytes: 1528