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

using VI = vector<int>;
using VVI = vector<VI>;
using PII = pair<int, int>;
using LL = long long;
using VL = vector<LL>;
using VVL = vector<VL>;
using PLL = pair<LL, LL>;
using VS = vector<string>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)

#define FF first
#define SS second
template<class S, class T>
istream& operator>>(istream& is, pair<S,T>& p){
  return is >> p.FF >> p.SS;
}
template<class S, class T>
ostream& operator<<(ostream& os, const pair<S,T>& p){
  return os << p.FF << " " << p.SS;
}
template<class T>
void maxi(T& x, T y){
  if(x < y) x = y;
}
template<class T>
void mini(T& x, T y){
  if(x > y) x = y;
}


const double EPS = 1e-10;
const double PI  = acos(-1.0);
const LL MOD = 1e9+7;
const int INF = 1e9;

struct EdgeEx{
  int to, cap, rev;
  EdgeEx(int to_=0, int cap_ = 0, int rev_ = 0)
	:to(to_), cap(cap_), rev(rev_){}
};


vector< vector<EdgeEx> > G; // (V, E)
void add_edge(int from, int to, int cap){
  G[from].push_back(EdgeEx(to, cap, G[to].size()));
  G[to].push_back(EdgeEx(from, 0, G[from].size()-1));
}

int max_flow_dfs(int u, int t, int f, vector<bool>& finished, vector<int>& level){
  if (u == t || f == 0) return f;
  if (finished[u]) return 0;
  finished[u] = true;
  for(auto& e: G[u]){
	if(level[e.to] > level[u]){
	  int fp = max_flow_dfs(e.to, t, min(f, e.cap), finished, level);
	  if(fp > 0) {
		e.cap -= fp;
		G[e.to][e.rev].cap += fp;
		finished[u] = false;
		return fp;
	  }
    }
  }
  return 0;
}
int maximumFlow(int s, int t) {
  int N = G.size();
  int total = 0;
  for(bool up=true;up;){
	up = false;
    vector<int> level(N, -1); level[s] = 0;
    queue<int> Q; Q.push(s);
    for(int d = N; !Q.empty() && level[Q.front()] < d; ) {
      int u = Q.front(); Q.pop();
      if (u == t) d = level[u];
      for(auto& e: G[u])
		if (e.cap > 0 && level[e.to] == -1)
		  Q.push(e.to), level[e.to] = level[u] + 1;
    }
    vector<bool> finished(N);
    for(int f = 1; f > 0; ) {
      f = max_flow_dfs(s, t, INF, finished, level);
      if (f == 0) break;
      total += f; up = true;
    }
  }
  return total;
}

int main(){
  cin.tie(0);
  ios_base::sync_with_stdio(false);

  int H, W;
  cin >> H >> W;
  VS vs(H);
  REP(y,H){
	cin >> vs[y];
  }

  int HW = H*W;
  G.assign(HW*2, vector<EdgeEx>());
  int S, T;
  REP(y,H) REP(x,W){
	int ix = y*W + x;
	if(vs[y][x] == 'S'){
	  S = ix;
	}
	else if(vs[y][x] == 'T'){
	  T = ix;
	}
  }
  if(S%W == T%W || S/W == T/W){
	cout << -1 << endl;
	return 0;
  }
  REP(y,H) REP(x,W) add_edge(y*W+x, y*W+x+HW, 1);

  REP(y,H){
	VI xs;
	REP(x,W){
	  if(vs[y][x] != '.'){
		xs.PB(x);
	  }
	}

	REP(i,SZ(xs)) REP(j,i){
	  add_edge(y*W+xs[i]+HW, y*W+xs[j],1);
	  add_edge(y*W+xs[j]+HW, y*W+xs[i],1);
	}
  }
  REP(x,W){
	VI ys;
	REP(y,H){
	  if(vs[y][x] != '.'){
		ys.PB(y);
	  }
	}

	REP(i,SZ(ys)) REP(j,i){
	  add_edge(ys[i]*W+x+HW, ys[j]*W+x,1);
	  add_edge(ys[j]*W+x+HW, ys[i]*W+x,1);
	}
  }

  cout << maximumFlow(S+HW, T) << endl;

  return 0;
}


Measured memory_bytes: 61568