#include <bits/stdc++.h>
#define ll long long
#define rep(i,n) for(ll (i)=0;(i)<(n);++(i))
using namespace std;

template<typename T>
struct Dinic{
    //辺
    struct edge
    {
        //行先と逆辺、revはid参照されているので、
        //追加された順に1,2,3,...となっている
        int to,rev;
        //cap は capacityの略
        T cap;
        edge(int to,T cap,int rev):to(to),cap(cap),rev(rev){};
    };
 
    const T INF;
 
    //グラフと探索済みかの配列
    vector<vector<edge>> graph;
    vector<int> iter,level;
 
    Dinic(int n):INF(numeric_limits<T>::max()){
        graph.resize(n);
    }
 
    void add_edge(int from, int to, T cap){
        //from ~ toにcapの辺を通す
        graph[from].emplace_back(to,cap,int(graph[to].size()));
        //to~from　に0容量の辺を通す
        graph[to].emplace_back(from,0,int(graph[from].size())-1);
    }
 
    //容量がある条件で最短距離の検索
    bool bfs(int s, int t){
        level.assign(graph.size(),-1);
        queue<int> que;
        level[s] = 0;
        que.push(s);
 
        while(!que.empty() and level[t] == -1){
            int p = que.front();
            que.pop();
 
            for(auto &e : graph[p]){
                if(e.cap > 0 and level[e.to] == -1){
                    que.push(e.to);
                    level[e.to] = level[p] + 1;
                }
            }
        }
 
        return level[t] != -1;
 
    }
 
    //ただのdfs探索
    //これは一本のパスについてflowを返していく
    T dfs(int v, const int t, T flow){
        //終了地点にきたらflowを返す
        if(v == t) return flow;
        for(int &i = iter[v]; i < graph[v].size(); i++){
            //流す余地があって未探索
            auto &e = graph[v][i];
            if(e.cap > 0 and (level[v] < level[e.to])){
                //このノード以降のフローを求める
                T d = dfs(e.to,t,min(flow,e.cap));
                if(d > 0){
                    e.cap -= d;
                    graph[e.to][e.rev].cap += d;
                    return d;
                }
            }
        }
        //ここにたどり着くのは増加パスがない時
        return 0;
    }
 
    T max_flow(int s,int t){
        T flow = 0;
        //
        //cout << " bfs?" << " " << bfs(s,t) << endl;
        while(bfs(s,t)){
            //探索回数のリセット
            iter.assign(graph.size(),0);
            
            T f = 0;
            //dfsで見つかる限りflowを追加
            
            while((f = dfs(s,t,INF)) > 0){
                
                flow += f;
            }
            
        }
        return flow;
    }
};
int main(){
    ll h,w;
    cin>>h>>w;
    vector<vector<char>> a(h,vector<char>(w));
    ll sx,sy,tx,ty;
    rep(i,h){
        rep(j,w){
            cin>>a[i][j];
            if(a[i][j]=='S'){
                a[i][j]='o';
                sx=i;
                sy=j;
            }
            if(a[i][j]=='T'){
                a[i][j]='o';
                tx=i;
                ty=j;
            }
        }
    }
    Dinic<ll> din(h+w+2);
    rep(i,h){
        rep(j,w){
            if(a[i][j]=='o'){
                din.add_edge(i, h+j, 1);
                din.add_edge(h+j, i, 1);
            }
        }
    }
    ll INF=1e9;
    din.add_edge(h+w,sx,INF);
    din.add_edge(h+w,h+sy,INF);
    din.add_edge(tx,h+w+1,INF);
    din.add_edge(h+ty,h+w+1,INF);
    ll ans=din.max_flow(h+w, h+w+1);
    if(ans>=INF){
        cout<<-1<<endl;
    }else{
        cout<<ans<<endl;
    }
}


Measured memory_bytes: 1152