// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;

#define FOR(i,a,b) for (int i=(a);i<=(b);++i)

#define ROF(i,a,b) for (int i=(a);i>=(b);--i)

typedef long long ll;

inline int read() {

	int x=0,s=1; char ch=getchar();

	while (ch<'0'||ch>'9') { if (ch=='-') s=-1; ch=getchar(); }

	while (ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); }

	return s*x;

}



const int MAXN=1000005,MAXM=4000006,INF=2147483647;

int en,u[MAXN],cur[MAXN];//cur为当前弧优化

struct edge{ int v,nt,c; }e[MAXM];

inline void clear(){ en=0; memset(u,-1,sizeof(u)); }

inline void addEdge(int x,int y,int z){//反向边为i^1

	e[en]=(edge){y,u[x],z}; u[x]=en++;

	e[en]=(edge){x,u[y],0}; u[y]=en++;

}

int S,T,nn,rear,head,Q[MAXN],dis[MAXN];

int BFS(){

	FOR(i,1,nn) dis[i]=INF;

	rear=head=0; dis[Q[++rear]=S]=0;

	while (head<rear) {

		int x=Q[++head];

		for (int i=u[x];~i;i=e[i].nt) {

			int j=e[i].v;

			if (e[i].c>0&&dis[j]>dis[x]+1) dis[Q[++rear]=j]=dis[x]+1;

		}

	}

	return dis[T]!=INF;

}

int DFS(int now,int flow) {

	if (now==T) return flow;

	int ans=0;

	for (int& i=cur[now];~i;i=e[i].nt) {

		int j=e[i].v;

		if (e[i].c>0&&dis[j]==dis[now]+1) {

			int k=min(e[i].c,flow); k=DFS(j,k);

			e[i].c-=k; e[i^1].c+=k; ans+=k; flow-=k;

		}

		if (!flow) break;

	}

	return ans;

}

int Dinic() {

	int ans=0;

	while (BFS()) {

		FOR(i,1,nn) cur[i]=u[i];

		ans+=DFS(S,INF);

	}

	return ans;

}

int n,m,q,a[MAXN],b[MAXN];

int main(){

	n=read(); m=read(); clear();

	S=n+m+1,nn=T=S+1;

	FOR(i,1,n)

		FOR(j,1,m) {

			char ch=getchar();

			while (ch!='.'&&ch!='o'&&ch!='S'&&ch!='T') ch=getchar();

			if (ch=='o') addEdge(i,n+j,1),addEdge(n+j,i,1);

			if (ch=='S') addEdge(S,i,n*m+1),addEdge(S,n+j,n*m+1);

			if (ch=='T') addEdge(i,T,n*m+1),addEdge(n+j,T,n*m+1);

		}

	int ans=Dinic();

	if (ans>=n*m) puts("-1");

	else printf("%d\n",ans);

	

	return 0;

}



/*

*/


// Optimized solution to the same problem (faster):
#include<iostream>

#include<string>

#include<algorithm>

#include<vector>

#include<iomanip>

#include<math.h>

#include<complex>

#include<queue>

#include<deque>

#include<stack>

#include<map>

#include<set>

#include<bitset>

#include<functional>

#include<assert.h>

#include<numeric>

using namespace std;

#define REP(i,m,n) for(int i=(int)(m) ; i < (int) (n) ; ++i )

#define rep(i,n) REP(i,0,n)

using ll = long long;

const int inf=1e9+7;

const ll longinf=1LL<<60 ;

const ll mod=1e9+7 ;





struct edge{int to;ll cap;int rev;};

struct Dinic{

private:

    int n;

    vector<vector<edge>> v;

    vector<int> dist,iter;

public:

    Dinic(int sz):n(sz),v(sz),dist(sz),iter(sz){}

    

    void addedge(int from,int to,ll cap){

        int x=v[to].size(),y=v[from].size();

        v[from].push_back({to,cap,x});

        v[to].push_back({from,0,y});

    }

    

    void bfs(int s){

        fill(dist.begin(),dist.end(),-1);

        queue<int> q;

        dist[s]=0;

        q.push(s);

        while(q.size()){

            int x=q.front();q.pop();

            rep(i,v[x].size()){

                edge &e=v[x][i];

                if(e.cap>0&&dist[e.to]<0){

                    dist[e.to]=dist[x]+1;

                    q.push(e.to);

                }

            }

        }

    }

    

    ll dfs(int x,int t,ll f){

        if(x==t)return f;

        for(int& i=iter[x];i<(int)v[x].size();++i){

            edge& e=v[x][i];

            if(e.cap>0&&dist[x]<dist[e.to]){

                ll d=dfs(e.to,t,min(f,e.cap));

                if(d>0){

                    e.cap-=d;

                    v[e.to][e.rev].cap+=d;

                    return d;

                }

            }

        }

        return 0;

    }



    ll max_flow(int s,int t){

        ll flow=0;

        while(1){

            bfs(s);

            if(dist[t]<0)return flow;

            fill(iter.begin(),iter.end(),0);

            ll f;

            while((f=dfs(s,t,1LL<<62))>0)flow+=f;

        }

    }

};

int main(){

    int h,w;

    cin>>h>>w;

    string s[h];

    rep(i,h)cin>>s[i];

    Dinic dn(h+w+2);

    rep(i,h)rep(j,w){

        if(s[i][j]!='.'){

            dn.addedge(i, h+j, 1);

            dn.addedge(h+j, i, 1);

        }

        if(s[i][j]=='S'){

            dn.addedge(h+w, i, inf);

            dn.addedge(h+w, j+h, inf);

        }

        if(s[i][j]=='T'){

            dn.addedge(i, h+w+1, inf);

            dn.addedge(j+h, h+w+1, inf);

        }

    }

    int ret = dn.max_flow(h+w, h+w+1);

    cout<<(ret>=inf?-1:ret)<<endl;

    return 0;

}

// Fastest known solution for this problem: