#include <bits/stdc++.h>
using namespace std;
#define FOR(i,a,b) for(ll i = (a); i < (ll)(b); i++)
#define REP(i,n) FOR(i,0,n)
#define YYS(x,arr) for(auto& x:arr)
#define PW(x) (1LL<<(x))
#define SZ(x) ((ll)(x).size())

#define pb emplace_back
#define fi first
#define se second
using ll = long long;
using P = pair<ll ,ll>;
//using Tu = tuple<ll, ll, ll>;
const ll INFLL = 1LL<<61LL;
const ll INF = 1LL<<61LL;
const ll MOD = 1e9+7;



using ld = long double;

template<class T> T &chmin( T &a , const T &b ){ return a = min(a,b); }
template<class T> T &chmax( T &a , const T &b ){ return a = max(a,b); }
template<class T> void UNIQUE(vector<T> &a){ a.erase(unique(a.begin(), a.end()), a.end()); }

template<class S, class T> ostream& operator << (ostream& os, const pair<S, T> v){
  os << "(" << v.first << ", " << v.second << ")"; return os;
}
template<class T> ostream& operator << (ostream& os, const vector<T> v){
  for(int i = 0; i < v.size(); i++){if(i > 0){os << " ";} os << v[i];} return os;
}
template<class T> ostream& operator << (ostream& os, const vector<vector<T>> v){
  for(int i = 0; i < v.size(); i++){if(i > 0){os << endl;} os << v[i];} return os;
}

ll in(){long long int x; assert(scanf("%lld", &x) == 1); return x;}
ld fin(){double x; assert(scanf("%lf", &x) == 1); return x;}
char yuyushiki[1000010]; string stin(){assert(scanf("%s", yuyushiki) == 1); return yuyushiki;}

using weight = ll;

struct MaxFlow{
  typedef ll weight;
  const weight zero = 0;
  const weight INF_WEIGHT = INFLL;
  struct edge{
    int to, rev;
    weight cap;
    edge(){}
    edge(int to, weight cap, int rev) : to(to), cap(cap), rev(rev){}
  };
  vector<vector<edge>> G;
  vector<int> level, iter;
  int n;
  void init(int size){
    n = size;
    G = vector<vector<edge>>(n, vector<edge>(0));
  }
  void add_edge(int from, int to, weight cap){
    G[from].pb(to, cap, SZ(G[to]));
    G[to].pb(from, zero, SZ(G[from])-1);
  }
  void bfs(int s){
    level = vector<int>(n, -1);
    queue<int> que;
    level[s] = 0;
    que.push(s);
    while(!que.empty()){
      int v = que.front();
      que.pop();
      YYS(e, G[v]){
        if(e.cap > zero && level[e.to] < 0){
          level[e.to] = level[v] + 1;
          que.push(e.to);
        }
      }
    }
  }
  weight dfs(int v, int t, weight f){
    if(v == t){
      return f;
    }
    for(int &i = iter[v]; i < G[v].size(); i++){
      edge &e = G[v][i];
      if(e.cap > zero && level[v] + 1 == level[e.to]){
        weight d = dfs(e.to, t, min(f, e.cap));
        if(d > zero){
          e.cap -= d;
          G[e.to][e.rev].cap += d;
          return d;
        }
      }
    }
    return zero;
  }
  weight max_flow(int s, int t){
    weight flow = zero;
    while(1){
      bfs(s);
      if(level[t] < 0){
        return flow;
      }
      iter = vector<int>(n, 0);
      weight f;
      while((f = dfs(s, t, INF_WEIGHT)) > zero){
        flow += f;
      }
    }
  }
};

vector<int> dx{-1, 0, 1, 0};
vector<int> dy{0, -1, 0, 1};
ll H, W;
ll id(ll y, ll x, bool isin){
  return (y * W + x) * 2 + isin;
}

int main(){
  cin >> H >> W;
  vector<string> area(H);
  for(int i=0;i<H;i++)
    cin >> area[i];
  MaxFlow flow;
  flow.init(H * W * 2);
  int sid, tid;
  for(int y=0;y<H;y++)
    for(int x=0;x<W;x++){
      if(area[y][x] == '.')
	continue;
      if(area[y][x] == 'o'){
	flow.add_edge(id(y, x, 1), id(y, x, 0), 1);
      }else{
	flow.add_edge(id(y, x, 1), id(y, x, 0), INF);
	if(area[y][x] == 'S')
	  sid = id(y, x, 0);
	else
	  tid = id(y, x, 1);
      }
      for(int k=0;k<4;k++){
	for(int step = 1;true;step++){
	  int nx = x + dx[k] * step;
	  int ny = y + dy[k] * step;
	  if(nx < 0 || nx >= W || ny < 0 || ny >= H)
	    break;
	  if(area[ny][nx] != '.'){
	    flow.add_edge(id(y, x, 0), id(ny, nx, 1), INF);
	    //cout << "from:" << y << " " << x << " " << k % 2 << " to:" << ny << " " << nx << " " << k % 2 << endl;
	  }
	}
      }
    }
  ll ans = flow.max_flow(sid, tid);
  if(ans >= INF)
    cout << -1 << endl;
  else
    cout << ans << endl;
}


Measured memory_bytes: 85376