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

#define int long long 



using namespace std;

const int Inf = 1e15;

const int maxn = 207;



struct Edge

{

    int u, v, flow;

    Edge(){};

    Edge(int u, int v, int flow) :u(u), v(v), flow(flow) {}

};



struct MaxFlow

{

    const int maxr = 1e5 + 7;

    int source, sink, h[maxn];

    vector<Edge> e;

    vector<int> adj[maxn];

    vector<int>::iterator cur[maxn];

    void Reset(int u, int v)

    {

        source = u, sink = v;

        for(int i = source; i <= sink; i++) adj[i] = {};

        e = {};

    }

    void AddEdge(int u, int v, int flow)

    {

        adj[u].push_back(e.size());

        e.push_back(Edge(u, v, flow));

        adj[v].push_back(e.size());

        e.push_back(Edge(v, u, 0));



    }

    bool BFS()

    {

        for(int i = source; i <= sink; i++) h[i] = 1e9;

        h[sink] = 0;

        queue<int> q;

        q.push(sink);

        while(!q.empty())

        {

            int gau = q.front();

            q.pop();

            for(auto i: adj[gau])

            {

                i ^= 1;

                int meo = e[i].u;

                if(e[i].flow == 0 || h[meo] != 1e9) continue;

                h[meo] = h[gau] + 1;

                if(meo == source) return true;

                q.push(meo);

            }

        }

        return false;

    }

    int DFS(int u, int FlowIn)

    {

        if(u == sink) return FlowIn;

        int FlowOut = 0;

        for(; cur[u] != adj[u].end(); cur[u]++)

        {

            int i = *cur[u];

            int v = e[i].v;

            if(e[i].flow == 0 || h[v] + 1 != h[u]) continue;

            int maxFlow = DFS(v, min(e[i].flow, FlowIn));

            FlowIn -= maxFlow;

            FlowOut += maxFlow;

            e[i].flow -= maxFlow;

            e[i ^ 1].flow += maxFlow;

            if(FlowIn == 0) break;

        }

        return FlowOut;

    }

    int FindMaxFLow()

    {

        int ans = 0;

        while(BFS())

        {

            for(int i = source; i <= sink; i++) cur[i] = adj[i].begin();

            ans += DFS(source, Inf);

        }

        return ans;

    }

} Dinitz;

int n, m;

int32_t main()

{

   ios_base::sync_with_stdio(0);

   cin.tie(0);

   if(fopen("test.inp", "r")) freopen("test.inp", "r" ,stdin);

   cin >> n >> m;

   Dinitz.Reset(0, n + m + 1);

   for(int i = 1; i <= n; i++)

   {

      for(int j = 1; j <= m; j++)

      {

         char s;

         cin >> s;

         if(s == '.') continue;

         if(s == 'S')

         {

            Dinitz.AddEdge(0, i, Inf);

            Dinitz.AddEdge(0, n + j, Inf);

         }

         else if(s == 'T') 

         {

            Dinitz.AddEdge(i, n + m + 1, Inf);

            Dinitz.AddEdge(n + j, n + m + 1, Inf);

         }

         else

         {

            Dinitz.AddEdge(i, n + j, 1);

            Dinitz.AddEdge(n + j, i, 1);

         }

      }

   }

   int ans = Dinitz.FindMaxFLow();

   if(ans >= Inf) cout << -1;

   else

   cout << ans;

}

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

#include<cstring>

#include<algorithm>

#include<queue>

#define inf 1e9

using namespace std;

struct node{

	int nxt,to,weigh;

}edge[400010];

int head[210],n,m,S,T,cnt=1,level[210],u,v,w;

queue<int> qu;

char s[110][110];

void addedge(int x,int y,int z){

	edge[++cnt].nxt=head[x];

	edge[cnt].to=y;

	edge[cnt].weigh=z;

	head[x]=cnt;

	edge[++cnt].to=x;

	edge[cnt].nxt=head[y];

	edge[cnt].weigh=0;

	head[y]=cnt;

}

bool bfs(){

	memset(level,-1,sizeof(level));

	level[S]=0;

	qu.push(S);

	while(!qu.empty()){

		int u=qu.front();

		qu.pop();

		for(int i=head[u];i;i=edge[i].nxt){

			int upup=edge[i].to;

			if(edge[i].weigh!=0 && level[upup]==-1){

				level[upup]=level[u]+1;

				qu.push(upup);

			}

		}

	}

	if(level[T]==-1)return false;

	return true;

}

int dfs(int x,int flow){

	if(x==T)return flow;

	int rest=0;

	for(int i=head[x];i;i=edge[i].nxt){

		int upup=edge[i].to;

		if(rest==flow)break;

		if(level[upup]==level[x]+1){

			int sum=dfs(upup,min(flow-rest,edge[i].weigh));

			rest+=sum,edge[i].weigh-=sum;edge[i^1].weigh+=sum;

		}

	} 

	return rest;

}

int Dinic(int S,int T){

	int ans=0;

	while(bfs())

		ans+=dfs(S,inf);

	return ans;

}

int main(){

	scanf("%d%d",&n,&m);

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

	for(int i=1;i<=n;i++)

		scanf("%s",s[i]+1);

	for(int i=1;i<=n;i++)

		for(int j=1;j<=m;j++){

			if(s[i][j]=='S')addedge(S,i,inf),addedge(S,j+n,inf);

			if(s[i][j]=='T')addedge(i,T,inf),addedge(j+n,T,inf);

			if(s[i][j]=='o')addedge(i,j+n,1),addedge(j+n,i,1);

		}

	int ans=Dinic(S,T);

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

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

		

}

// Fastest known solution for this problem: