#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#include <climits>

#define rep(i, m, n) for(int i=int(m);i<int(n);i++)
#define EACH(i, c) for (auto &(i): c)
#define all(c) begin(c),end(c)
#define EXIST(s, e) ((s).find(e)!=(s).end())
#define SORT(c) sort(begin(c),end(c))
#define pb emplace_back
#define MP make_pair
#define SZ(a) int((a).size())

//#define LOCAL 0
//#ifdef LOCAL
//#define DEBUG(s) cout << (s) << endl
//#define dump(x)  cerr << #x << " = " << (x) << endl
//#define BR cout << endl;
//#else
//#define DEBUG(s) do{}while(0)
//#define dump(x) do{}while(0)
//#define BR
//#endif


//改造
typedef long long int ll;
using namespace std;
#define INF (1 << 20)
#define INFl (ll)5e15
#define DEBUG 0 //デバッグする時1にしてね
#define dump(x)  cerr << #x << " = " << (x) << endl
#define MOD 1000000007
//ここから編集する
class Flow{
public:
    struct edge{int to,cap,rev;};
//    vector<vector<edge> > G;
//    vector<bool> used;
    vector<edge> G[20000];
    bool used[20000];

    //0 ~ maxSize-1 のフローを構築できるようにする
    explicit Flow(unsigned maxSize){
//        G.resize(200,vector<edge>());
//        used.resize(200,false);
    }

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

    //増加パスを探す
    int dfs(int v,int t,int 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){
                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(;;){
            rep(i,0,20001) used[i] = false;
            int f = dfs(s,t,INF);
            if(f == 0) return flow;
            flow += f;
        }
    }

};

int main() {
    int H,W;
    cin.tie(0);
    ios::sync_with_stdio(false);
    cin >> H >> W;
    char masu[100][100];
//    rep(i,0,H){
//        scanf("%s",masu[i]);
//    }
    rep(i,0,H){
        rep(j,0,W){
            cin >> masu[i][j];
//            printf("%c",masu[i][j]);
        }
//        cout << endl;
    }


    int start_h = -1,start_w = -1,end_h = -1,end_w = -1;
    rep(i,0,H){
        rep(j,0,W){
            if(masu[i][j] == 'S'){
                start_h = i;
                start_w = j;
            }
            if(masu[i][j] == 'T'){
                end_h = i;
                end_w = j;
            }
        }
    }
    if(start_h == end_h || start_w == end_w){
        cout << -1 << endl;
        return 0;
    }
    Flow flow(2*H*W);

    int S = start_h * W + start_w;
    int T = end_h * W + end_w;
    int to = H * W;

    rep(i,0,H){
        rep(j,0,W){
            if(masu[i][j] == '.') continue;

            int from = i * W + j;
            flow.add_edge(from+to,from,1);

            rep(a,0,H){
                if(a != i){
                    if(masu[a][j] != '.'){
                        flow.add_edge(i*W+j,a*W + j+to,1);
                    }
                }
            }
            rep(b,0,W){
                if(b != j){
                    if(masu[i][b] != '.'){
                        flow.add_edge(i*W+j,i*W + b+to,1);
                    }
                }
            }
        }
    }

    cout << flow.max_flow(S,T+to) << endl;



    return 0;
}


Measured memory_bytes: 63232