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



using namespace std;



const int inf = 1e9;



struct Dinic {

   int n, s, t;

   struct Edge {

      int to, cap, flow, rev;

      Edge(int to = 0, int cap = 0, int flow = 0, int rev = 0) :

         to(to), cap(cap), flow(flow), rev(rev) {}

   };

   vector<int> d;

   vector<int> ptr;

   vector<vector<Edge>> g;

   Dinic(int n = 0, int s = 0, int t = 0) :

      n(n), s(s), t(t), d(n), ptr(n), g(n) {}

   void addEdge(int u, int v, int cap) {

      g[u].emplace_back(v, cap, 0, g[v].size());

      g[v].emplace_back(u, 0, 0, g[u].size() - 1);

   }

   bool bfs() {

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

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

      queue<int> q;

      d[s] = 0;

      q.push(s);

      while (!q.empty()) {

         int u = q.front();

         q.pop();

         for (auto e : g[u]) {

            if (d[e.to] == -1 && e.cap > e.flow) {

               d[e.to] = d[u] + 1;

               q.push(e.to);

            }

         }

      }

      return d[t] != -1;

   }

   int dfs(int u, int flow) {

      if (u == t) {

         return flow;

      }

      for (int &i = ptr[u]; i < g[u].size(); ++i) {

         auto &e = g[u][i];

         if (e.cap <= e.flow || d[e.to] != d[u] + 1) continue;

         int nxt = dfs(e.to, min(flow, e.cap - e.flow));

         if (nxt) {

            e.flow += nxt;

            g[e.to][e.rev].flow -= nxt;

            return nxt;

         }

      }

      return 0;

   }

   int maxFlow() {

      int ans = 0;

      while (bfs()) {

         while (true) {

            int now = dfs(s, inf);

            if (now) ans += now;

            else break;

         }

      }

      return ans;

   }

   vector<int> path;

   void trace(int v) {

      path.emplace_back(v);

      for (auto &e : g[v]) {

         if (e.flow > 0) {

            e.flow--;

            return trace(e.to);

         }

      }

   }

   vector<int> getPath() {

      path.clear();

      trace(s);

      return path;

   }

};



int main() {

   ios_base::sync_with_stdio(false);

   int N, M; cin >> N >> M;

   vector<string> A(N);

   Dinic dn(N + M + 2, N + M, N + M + 1);

   for (int i = 0; i < N; ++i) {

      cin >> A[i];

      for (int j = 0; j < M; ++j) {

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

            dn.addEdge(N + M, i, inf);

            dn.addEdge(N + M, j + N, inf);

         } else if (A[i][j] == 'T') {

            dn.addEdge(i, N + M + 1, inf);

            dn.addEdge(j + N, N + M + 1, inf);

         } else if (A[i][j] == 'o') {

            dn.addEdge(i, j + N, 1);

            dn.addEdge(j + N, i, 1);

         }

      }

   }

   int ans = dn.maxFlow();

   if (ans >= inf) ans = -1;

   cout << ans << "\n";

   return 0;

}


// 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: