#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <map>
#include <set>
#include <utility>
#include <vector>
#include <queue>
#include <cmath>
#define read(X) scanf("%d",&X);
#define readLL(X) cin>>X;
#define readN(N,a) for(int i=0;i<N;i++)scanf("%lld",&a[i]);
#define LL long long
#define FOR(x,a,b) for(int x=a;x<b;x++)
#define pii pair<int,int>
#define INF 3000000
using namespace std;

namespace maxflow{

    const int MAXN=100005;
    const int MAXM=100005;

    long long bottleneck;
    int node_count, e;
    int x, y, w;
    int p[MAXN], edge[MAXN];
    int last[MAXN];
    int _prev[MAXM];
    int to[MAXM];
    long long c[MAXM], f[MAXM];
    vector<int> e_x, e_y;
    vector<long long> e_w;

    void __add(int x, int y, long long w){
        _prev[e] = last[x];
        last[x] = e;
        to[e] = y;
        c[e] = w;
        f[e] = 0;
        e++;
        
        _prev[e] = last[y];
        last[y] = e;
        to[e] = x;
        c[e] = 0;
        f[e] = 0;
        e++;
    }

    /* find augmenting path in residual graph */
    bool path(int u, int v){
        queue<int> Q;
        int C, F;
        
        for(int i = 0; i < node_count; i++) p[i] = -1;
        Q.push(u);
        p[u] = u;
        while(!Q.empty())
        {   
            x = Q.front(), Q.pop();
            //cout<<x<<endl;
            
            if(x == v) return true;
            for(int i=last[x]; i!=-1; i=_prev[i])
            {   
                //cout<<i<<endl;
                y = to[i];
                F = f[i];
                C = c[i];
                if(p[y] == -1 && C > F)
                {   
                    p[y] = x;
                    edge[y] = i;
                    Q.push(y);
                }
            }
        }
        return false;
    }

    /* send flow through augmenting path */
    int send(int u, int v)
    {   
        bottleneck = INF;
        int x, y, index, sym;
        y = v;

        while(p[y] != y)
        {   
            x = p[y];
            index = edge[y];
            bottleneck = (bottleneck > c[index]-f[index] ? c[index]-f[index] : bottleneck);
            y = x;
        }

        y = v;
        while(p[y] != y)
        {   
            x = p[y];
            index = edge[y];
            f[index] += bottleneck;
            f[index^1] -= bottleneck;
            y = x;
        }

        return bottleneck;
    }

    void add(int x,int y, int w){
        e_x.push_back(x);
        e_y.push_back(y);
        e_w.push_back(w);
    }

    long long flow(int s, int t){
        long long res = 0;
        
        memset(last, -1, sizeof(last));
        
        e = 0;
        int tmp = e_x.size();
        for (int i=0;i<tmp;i++)
            __add(e_x[i], e_y[i], e_w[i]);

        while(path(s, t)){
            res += send(s, t);
        }
        return res;
    }
}

int N,M;
char lho[111][111];
int nid[111][111];
int main(){
    read(N);
    read(M);

    /* build graph */
   

    FOR(i,0,N){
        scanf("%s",lho[i]);
    }
    //cout<<"dah"<<endl;
    maxflow::node_count = N+M+2;
    int s = N+M;
    int t = N+M+1;
    FOR(i,0,N)
        FOR(j,0,M){
            if (lho[i][j]=='.') continue;
            if (lho[i][j]=='S'){
                 maxflow::add(s,i,INF);  
                 maxflow::add(s,N+j,INF);   
            }
            
            if (lho[i][j]=='T'){
                maxflow::add(i,t,INF);  
                maxflow::add(N+j,t,INF); 
            }
            if (lho[i][j]!='.'){
                maxflow::add(i,N+j,1);
                maxflow::add(N+j,i,1);
            }
        }

    //cout<<"wut "<<s<<" "<<t<<endl;
    int flow = maxflow::flow(s,t);
    if (flow >= INF) flow = -1;
    printf("%d\n", flow);
    
    return 0;
}


Measured memory_bytes: 2044