#include <iostream>
#include <algorithm>
#include <iomanip>
#include <string>
#include <functional>
#include <utility>
#include <queue>
#include <vector>
#include <string>
#include <stack>
#define rep(i,n) for(ll i=0;i<n;i++)
using namespace std;
typedef long long int ll;
const ll  MOD = 1000000007;
typedef pair<ll,ll> P;
const ll INF = 100100100100100100;

ll H,W;
ll s_x,s_y,t_x,t_y;
string s[110];
struct edge{ ll to,cap,rev;};
vector<edge> G[20100];//to,rev
bool used[20100];

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

ll dfs(ll v,ll t ,ll f){
  if(v == t) return f;
  used[v] = true;
  for(int i=0;i<G[v].size();i++){
    edge &e = G[v][i];
    if(!used[e.to] && e.cap > 0){
      ll 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;
}
ll max_flow(ll s, ll t){
  ll flow = 0;
  for(;;){
    rep(i,10100){
      used[i] = 0;
    }
    ll f = dfs(s,t,100100100100100100);
    if(f == 0) return flow;
    flow += f;
  }
}

int main(){
  cin >> H >> W;
  rep(i,H){
    cin >> s[i];
    rep(j,W){
      if(s[i][j] == 'S'){
        s_x = j;
        s_y = i;
      }
      else if(s[i][j] == 'T'){
        t_x = j;
        t_y = i;
      }
    }
  }
  if(s_x == t_x || s_y == t_y){
    cout << "-1" << endl;
    return 0;
  }
  rep(i,H){
    rep(j,W){
      if(s[i][j] != '.'){
        if(s[i][j] == 'S'){
          add_edge(10000,i,INF);
          add_edge(10000,j+1000,INF);
        }
        else if(s[i][j] == 'T'){
          add_edge(i,10001,INF);
          add_edge(j+1000,10001,INF);
        }
        else{
          add_edge(i,j+1000,1);
          add_edge(j+1000,i,1);
        }
      }
    }
  }
  cout << max_flow(10000,10001) << endl;
}
