#pragma GCC optimize("Ofast")
#include <cstdio>
#include <cstdlib>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
#include <bitset>
#include <cmath>
#include <limits>
#include <iostream>
#include <map>
#include <set>
#include <tuple>
#include <iomanip>
#include <functional>
#include <complex>

using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<int,ll> pil;
typedef pair<ll,int> pli;
typedef pair<ll,ll> pll;

template<class T,class U>constexpr bool chmin(T&a,const U b){if(a<=b)return false;a=b;return true;}
template<class T,class U>constexpr bool chmax(T&a,const U b){if(a>=b)return false;a=b;return true;}
#define bit(n,k) ( (n>>k)&1 )

//デバッグ
template<class T>
void Vout(vector<T> &V){
    cout<<"\nstart\n";
    const int sz=V.size();
    for(int i=0;i<sz;i++){
        cout<<i<<" "<<V[i]<<'\n';
    }
    cout<<"end\n"<<endl;
}

template<class T>
void VPout(vector<T> &V){
    cout<<"\nstart\n";
    const int sz=V.size();
    for(int i=0;i<sz;i++){
        cout<<i<<" "<<V[i].first<<" "<<V[i].second<<'\n';
    }
    cout<<"end\n"<<endl;
}


//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


constexpr int MAX=1<<30;
constexpr ll INF=1LL<<62;
constexpr int MOD=1e9+7;
int dx[]={1,-1,0,0},dy[]={0,0,-1,1};

//__builtin_popcount(S);
//#define int ll
//vector<vector<int>> data(3, vector<int>(4));
//vector.resize(a,vector<int>(b,-1));
//vector<vector<vector<要素の型>>> 変数名(要素数1, vector<vector<要素の型>>(要素数2, vector<要素の型>(要素数3, 初期値)));


template<typename T>
struct Dinic{
    struct edge{
        int to;
        T cap;
        int rev;
    };
    const T inf;
    const T zero;
    int sz;
    vector< vector<edge> > graph;
    vector<int> dist,iter;

    Dinic(const int n,const T inf,const T zero) : inf(inf),zero(zero),graph(n),sz(n){}

    void add_edge(const int from,const int to,const T cap){
        graph[from].emplace_back((edge){to,cap,(int)graph[to].size()});
        graph[to].emplace_back((edge){from,0,(int)graph[from].size()-1});
    }

    bool bfs(int s,int t){
        dist.assign(sz,-1);
        queue<int> que;
        dist[s]=0;
        que.push(s);
        while(!que.empty() && dist[t]==-1){
            int now=que.front();
            que.pop();
            for(auto &e:graph[now]){
                if(e.cap>0 && dist[e.to]==-1){
                    dist[e.to]=dist[now]+1;
                    que.push(e.to);
                }
            }
        }
        return dist[t]!=-1;
    }

    T dfs(int idx,const int t,T flow){
        if(idx==t) return flow;
        for(int &i=iter[idx];i<graph[idx].size();i++){
            edge &e=graph[idx][i];
            if(e.cap>0 && dist[idx]<dist[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 zero;
    }

    T max_flow(int s,const int t){
        T ret=0;
        while(bfs(s,t)){
            iter.assign(sz,0);
            T f=0;
            while((f=dfs(s,t,inf))>zero) ret+=f;
        }
        return ret;
    }
};

int n,m;
vector<int> s,t;

const double eps=10e-7;

bool check(int ans,double mid,Dinic<double> flow){
    for(int i=0;i<m;i++){
        flow.add_edge(1+n+i,n+m+1,t[i]*mid);
    }
    double x=flow.max_flow(0,n+m+1);
    if(ans-x>eps) return true;
    return false;

}


signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr); 
    cout<<fixed<<setprecision(10);

    int h,w;
    cin>>h>>w;

    char a[110][110];
    int s,t;
    Dinic<ll> flow(h+w+2,MAX,0LL);

    for(int i=0;i<h;i++){
        for(int j=0;j<w;j++){
            cin>>a[i][j];
            if(a[i][j]=='S'){
                flow.add_edge(0,i+1,MAX);
                flow.add_edge(0,h+1+j,MAX);
            }else if(a[i][j]=='T'){
                t=i*w+j;
                flow.add_edge(i+1,h+1+w,MAX);
                flow.add_edge(h+1+j,h+w+1,MAX);
            }
        }
    }
    
    for(int i=0;i<h;i++){
        for(int j=0;j<w;j++){
            if(a[i][j]=='.') continue;
            flow.add_edge(i+1,h+1+j,1);
            flow.add_edge(h+1+j,i+1,1);
        }
    }
    ll x=flow.max_flow(0,h+1+w);
    if(x>=MAX) cout<<-1<<endl;
    else cout<<x<<endl;
}

Measured memory_bytes: 1536