// Slower C++ solution:
#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;

}



/*

*/


// Faster C++ solution for the same problem (measured speedup: 4.916071139004739x):
#include<bits/stdc++.h>



using namespace std;



template <typename T>

class flow_graph {

 public:

  static constexpr T eps = (T) 1e-9;

 

  struct edge {

    int from;

    int to;

    T c;

    T f;

  };

 

  vector<vector<int>> g;

  vector<edge> edges;

  int n;

  int st;

  int fin;

  T flow;

 

  flow_graph(int _n, int _st, int _fin) : n(_n), st(_st), fin(_fin) {

    assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin);

    g.resize(n);

    flow = 0;

  }

 

  void clear_flow() {

    for (const edge &e : edges) {

      e.f = 0;

    }

    flow = 0;

  }

   

  int add(int from, int to, T forward_cap, T backward_cap) {

    assert(0 <= from && from < n && 0 <= to && to < n);

    int id = (int) edges.size();

    g[from].push_back(id);

    edges.push_back({from, to, forward_cap, 0});

    g[to].push_back(id + 1);

    edges.push_back({to, from, backward_cap, 0});

    return id;

  }

};

 

template <typename T>

class dinic {

 public:

  flow_graph<T> &g;

 

  vector<int> ptr;

  vector<int> d;

  vector<int> q;

 

  dinic(flow_graph<T> &_g) : g(_g) {

    ptr.resize(g.n);

    d.resize(g.n);

    q.resize(g.n);

  }

 

  bool expath() {

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

    q[0] = g.fin;

    d[g.fin] = 0;

    int beg = 0, end = 1;

    while (beg < end) {

      int i = q[beg++];

      for (int id : g.g[i]) {

        const auto &e = g.edges[id];

        const auto &back = g.edges[id ^ 1];

        if (back.c - back.f > g.eps && d[e.to] == -1) {

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

          if (e.to == g.st) {

            return true;

          }

          q[end++] = e.to;

        }

      }

    }

    return false;

  }

   

  T dfs(int v, T w) {

    if (v == g.fin) {

      return w;

    }

    int &j = ptr[v];

    while (j >= 0) {

      int id = g.g[v][j];

      const auto &e = g.edges[id];

      if (e.c - e.f > g.eps && d[e.to] == d[v] - 1) {

        T t = dfs(e.to, min(e.c - e.f, w));

        if (t > g.eps) {

          g.edges[id].f += t;

          g.edges[id ^ 1].f -= t;

          return t;

        }

      }

      j--;

    }

    return 0;

  }

 

  T max_flow() {

    while (expath()) {

      for (int i = 0; i < g.n; i++) {

        ptr[i] = (int) g.g[i].size() - 1;

      }

      T big_add = 0;

      while (true) {

        T add = dfs(g.st, numeric_limits<T>::max());

        if (add <= g.eps) {

          break;

        }

        big_add += add;

      }

      if (big_add <= g.eps) {

        break;

      }

      g.flow += big_add;

    }

    return g.flow;

  }

 

  vector<bool> min_cut() {

    max_flow();

    vector<bool> ret(g.n);

    for (int i = 0; i < g.n; i++) {

      ret[i] = (d[i] != -1);

    }

    return ret;

  }

};



int main() {

	ios::sync_with_stdio(0);

	cin.tie(0);

	int n,m;

	cin >> n >> m;

	vector<string> s(n);

	int st,ed;

	int S = m + n;

	int T = S + 1;

	flow_graph<int> f(T+1,S,T);

	dinic<int> d(f);

	int oo = (int)2e7;

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

		cin >> s[i];

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

			if (s[i][j] == '.') continue;

			f.add(i,n+j,1,1);

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

				f.add(S,i,oo,0);

				f.add(S,n+j,oo,0);

			}

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

				f.add(i,T,oo,0);

				f.add(n+j,T,oo,0);

			}

		}

	}

	int ans;

	if ((ans = d.max_flow()) >= oo) cout <<"-1";else cout << ans;

}