#include <algorithm>
#include <cmath>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <set>
#include <tuple>
#include <vector>

using namespace std;

#define rep(i, n) for (int64_t i = 0; i < (n); i++)
#define irep(i, n) for (int64_t i = 0; i <= (n); i++)
#define rrep(i, n) for (int64_t i = (n)-1; i >= 0; i--)
#define rirep(i, n) for (int64_t i = n; i >= 0; i--)

struct FlowNetwork {
  struct Edge {
    int from;
    int to;
    int capacity;
    int flow;
  };

  vector<vector<int>> outEdge, inEdge;
  vector<Edge> edgeData;

  FlowNetwork(int size) : outEdge(size), inEdge(size) {}

  void addEdge(const int from, const int to, const int64_t capacity) {
    const int eId = edgeData.size();
    Edge eData;
    eData.from = from;
    eData.to = to;
    eData.flow = 0;
    eData.capacity = capacity;
    edgeData.push_back(eData);
    outEdge[from].push_back(eId);
    inEdge[to].push_back(eId);
  }

  void maxflow(const int source, const int sink) {
    const int n = outEdge.size();
    const int m = edgeData.size();

    while (true) {
      // check if reachable to sink
      vector<int> parent(n, -1);
      queue<int> q;
      q.push(source);

      while (!q.empty()) {
        int v = q.front();
        q.pop();

        for (const int e : outEdge[v]) {
          const Edge &data = edgeData[e];
          const int nv = data.to;
          if (parent[nv] < 0 && data.capacity - data.flow > 0) {
            q.push(nv);
            parent[nv] = e;
          }
        }

        for (const int e : inEdge[v]) {
          const Edge &data = edgeData[e];
          const int nv = data.from;
          if (parent[nv] < 0 && data.flow > 0) {
            q.push(nv);
            parent[nv] = e;
          }
        }
      }

      if (parent[sink] < 0) {
        break;
      }

      // select path from source to sink
      int d = 1'000'000'000;
      int v = sink;
      while (v != source) {
        const int e = parent[v];
        const Edge &data = edgeData[e];
        if (data.to == v) {
          d = min(d, data.capacity - data.flow);
          v = data.from;
        } else {
          d = min(d, data.flow);
          v = data.to;
        }
      }

      // update flow on the path
      v = sink;
      while (v != source) {
        const int e = parent[v];
        Edge &data = edgeData[e];
        if (data.to == v) {
          data.flow += d;
          v = data.from;
        } else {
          data.flow -= d;
          v = data.to;
        }
      }
    }
  }
};

int main() {
  const int INF = 1'000'000'000;

  int H, W;
  cin >> H >> W;

  vector<string> grid(H);
  rep(i, H) { cin >> grid[i]; }

  int source, sink;
  int sx, sy, tx, ty;
  rep(i, H) rep(j, W) {
    const int pointId = i * W + j;
    if (grid[i][j] == 'S') {
      source = pointId;
      sx = i;
      sy = j;
    }
    if (grid[i][j] == 'T') {
      sink = pointId;
      tx = i;
      ty = j;
    }
  }
  if (sx == tx || sy == ty) {
    cout << -1 << endl;
    return 0;
  }

  const int nodeNum = 2 * H * W + 2 * (H + W);
  FlowNetwork net(nodeNum);
  rep(i, H) rep(j, W) {
    const int pointId = i * W + j;
    const int fromId = pointId * 2;
    const int toId = pointId * 2 + 1;
    const int capacity = (pointId == source || pointId == sink) ? INF : 1;

    net.addEdge(fromId, toId, capacity);
  }

  rep(i, H) rep(j, W) {
    const int pointId = i * W + j;

    if (grid[i][j] != '.') {
      const int offset = H * W * 2;

      net.addEdge(2 * pointId + 1, offset + i, INF);
      net.addEdge(offset + i, 2 * pointId, INF);
      net.addEdge(2 * pointId + 1, offset + H + j, INF);
      net.addEdge(offset + H + j, 2 * pointId, INF);
    }
  }
  int result = 0;
  net.maxflow(source * 2, sink * 2);
  for (const int e : net.inEdge[sink * 2]) {
    result += net.edgeData[e].flow;
  }
  cout << result << endl;

  return 0;
}

Measured memory_bytes: 3572