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

#include <vector>
#include <queue>
#include <algorithm>
#include <numeric>
#include <functional>

struct edge { int to, cap, rev, cost; };

constexpr int MAX_V = 40000;
vector<edge> G[MAX_V];
int level[MAX_V];
int iter[MAX_V];

void add_edge(int from, int to, int cap, int cost = 0){
	G[from].push_back(edge{ to, cap, (int)G[to].size(),cost });
	G[to].push_back(edge{ from,0,(int)G[from].size() - 1,-cost });
}

void bfs(int s) {
	fill_n(level, MAX_V, -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 dfs(int v, int t, int f) {
	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 = 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 (;;) {
		bfs(s);
		if (level[t] < 0)return flow;
		fill_n(iter, MAX_V, 0);
		int f;
		while ((f = dfs(s, t, numeric_limits<int>::max()))>0) {
			flow += f;
		}
	}
}

typedef pair<int, int> P;
int V;
int h[MAX_V];
int dist[MAX_V];
int prevv[MAX_V], preve[MAX_V];

int min_cost_flow(int s, int t, int f) {
	int res = 0;
	fill_n(h, V, 0);
	while (f > 0) {
		priority_queue<P, vector<P>, greater<P>> que;
		fill_n(dist, V, numeric_limits<int>::max());
		dist[s] = 0;
		que.push({ 0,s });
		while (!que.empty()) {
			P p = que.top(); que.pop();
			int v = p.second;
			if (dist[v] < p.first)continue;
			for (int i = 0; i < G[v].size(); i++) {
				edge &e = G[v][i];
				if (e.cap > 0 && dist[e.to]>dist[v] + e.cost + h[v] - h[e.to]) {
					dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
					prevv[e.to] = v;
					preve[e.to] = i;
					que.push({ dist[e.to],e.to });
				}
			}
		}
		if (dist[t] == numeric_limits<int>::max()) {
			return -1;
		}
		for (int v = 0; v < V; v++)h[v] += dist[v];

		int d = f;
		for (int v = t; v != s; v = prevv[v]) {
			d = min(d, G[prevv[v]][preve[v]].cap);
		}
		f -= d;
		res += d*h[t];
		for (int v = t; v != s; v = prevv[v]) {
			edge &e = G[prevv[v]][preve[v]];
			e.cap -= d;
			G[v][e.rev].cap += d;
		}
	}
	return res;
}

int main(){
  int h,w;
  cin>>h>>w;
  int size=h*w;
  vector<string> a(h);
  int s;
  int t;
  const int INF=1e5;
  for(int i=0;i<h;i++) cin>>a[i];
  for(int i=0;i<h;i++){
    for(int j=0;j<w;j++){
      int base=i+h*j;
      int camp=base+size;
      int hcamp=base+size*2;
      int wcamp=base+size*3;
      if(a[i][j]=='o'){
	add_edge(camp,base,1);
	add_edge(hcamp,camp,INF);
	add_edge(wcamp,camp,INF);
	add_edge(base,hcamp,INF);
	add_edge(base,wcamp,INF);
      }
      else if(a[i][j]=='S'||a[i][j]=='T'){
	if(a[i][j]=='S'){
	  s=base;
	}
	else{
	  t=base;
	}
	add_edge(camp,base,INF);
	add_edge(hcamp,camp,INF);
	add_edge(wcamp,camp,INF);
	add_edge(base,hcamp,INF);
	add_edge(base,wcamp,INF);
      }
      if(i!=h-1){
	int nhc=(i+1)+h*j+size*2;
	add_edge(hcamp,nhc,INF);
	add_edge(nhc,hcamp,INF);
      }
      if(j!=w-1){
	int nwc=i+h*(j+1)+size*3;
	add_edge(wcamp,nwc,INF);
	add_edge(nwc,wcamp,INF);
      }
    }
  }

  int res=max_flow(s,t);
  if(res>=1e5) cout<<-1<<endl;
  else cout<<res<<endl;
  
  return 0;
}


Measured memory_bytes: 5888