#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <string>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <functional>
#include <iterator>
#include <limits>
#include <numeric>
#include <utility>
#include <type_traits>
#include <cmath>
#include <cassert>
#include <cstdio>

using namespace std;
using namespace placeholders;

using LL = long long;
using ULL = unsigned long long;
using VI = vector< int >;
using VVI = vector< vector< int > >;
using VS = vector< string >;
using ISS = istringstream;
using OSS = ostringstream;
using PII = pair< int, int >;
using VPII = vector< pair< int, int > >;
template < typename T = int > using VT = vector< T >;
template < typename T = int > using VVT = vector< vector< T > >;
template < typename T = int > using LIM = numeric_limits< T >;

template < typename T > inline istream& operator>>( istream &s, vector< T > &v ){ for ( T &t : v ) { s >> t; } return s; }
template < typename T > inline ostream& operator<<( ostream &s, const vector< T > &v ){ for ( int i = 0; i < int( v.size() ); ++i ){ s << ( " " + !i ) << v[i]; } return s; }

template < typename T > struct getv_fmt;
template <> struct getv_fmt<       int >{ static constexpr const char *fmt = "%d"; };
template <> struct getv_fmt< long long >{ static constexpr const char *fmt = "%lld"; };
template < typename T > void getv( std::vector< T > &v ){ for_each( begin( v ), end( v ), []( T &a ){ scanf( getv_fmt< T >::fmt, &a ); } ); };

template < typename T > inline T fromString( const string &s ) { T res; istringstream iss( s ); iss >> res; return res; }
template < typename T > inline string toString( const T &a ) { ostringstream oss; oss << a; return oss.str(); }

#define NUMBERED( name, number ) NUMBERED2( name, number )
#define NUMBERED2( name, number ) name ## _ ## number
#define REP1( n ) REP2( NUMBERED( REP_COUNTER, __LINE__ ), n )
#define REP2( i, n ) REP3( i, 0, n )
#define REP3( i, m, n ) for ( int i = ( int )( m ); i < ( int )( n ); ++i )
#define GET_REP( a, b, c, F, ... ) F
#define REP( ... ) GET_REP( __VA_ARGS__, REP3, REP2, REP1 )( __VA_ARGS__ )
#define FOR( e, c ) for ( auto &&e : c )
#define ALL( c ) begin( c ), end( c )
#define AALL( a ) ( remove_all_extents< decltype( a ) >::type * )a, ( remove_all_extents< decltype( a ) >::type * )a + sizeof( a ) / sizeof( remove_all_extents< decltype( a ) >::type )
#define DRANGE( c, p ) begin( c ), begin( c ) + ( p ), end( c )

#define SZ( v ) ( (int)( v ).size() )
#define EXIST( c, e ) ( ( c ).find( e ) != ( c ).end() )

template < typename T > inline bool chmin( T &a, const T &b ){ if ( b < a ) { a = b; return true; } return false; }
template < typename T > inline bool chmax( T &a, const T &b ){ if ( a < b ) { a = b; return true; } return false; }

#define PB push_back
#define EM emplace
#define EB emplace_back
#define BI back_inserter

#define MP make_pair
#define fst first
#define snd second

#define DUMP( x ) cerr << #x << " = " << ( x ) << endl

constexpr int INF = 20000;

// 最大流（ Dinic 法 ） O( |E||V|^2 )
class Dinic
{
	struct Edge
	{
		int to, cap, rev;
		Edge( int t, int c, int r ) : to( t ), cap( c ), rev( r ) {}
	};

	vector< vector<Edge> > G;
	vector<int> distance, done;

public:
	Dinic( int V ) : G( V ), distance( V ), done( V )
	{
		return;
	}

	void connect( int from, int to, int cost )
	{
		G[ from ].push_back( Edge( to, cost, G[ to ].size() ) );
		G[ to ].push_back( Edge( from, 0, G[ from ].size() - 1 ) );
		return;
	}

	int solve( int s, int t )
	{
		int res = 0;
		while ( true )
		{
			bfs( s );
			if ( distance[t] < 0 )
			{
				return res;
			}

			fill( done.begin(), done.end(), 0 );
			for ( int f; ( f = dfs( s, t, numeric_limits<int>::max() ) ) > 0; res += f );
		}
	}

private:
	void bfs( int s )
	{
		fill( distance.begin(), distance.end(), -1 );
		distance[s] = 0;
		
		queue<int> que;
		que.push( s );
		while ( !que.empty() )
		{
			int v = que.front();
			que.pop();

			for ( int i = 0; i < (int)G[v].size(); ++i )
			{
				Edge &e = G[v][i];
				if ( e.cap > 0 && distance[ e.to ] < 0 )
				{
					distance[ e.to ] = distance[v] + 1;
					que.push( e.to );
				}
			}
		}

		return;
	}

	int dfs( int v, int t, int f )
	{
		if ( v == t )
		{
			return f;
		}

		for ( int &i = done[v]; i < (int)G[v].size(); ++i )
		{
			Edge &e = G[v][i];
			if ( e.cap > 0 && distance[v] < distance[ e.to ] )
			{
				int d = dfs( e.to, t, min( f, e.cap ) );
				if ( d > 0 )
				{
					e.cap -= d;
					G[ e.to ][ e.rev ].cap += d;
					return d;
				}
			}
		}

		return 0;
	}
};
// Dinic( |V| )
// connect( from, to, cap )
// solve( s, t )

int main()
{
	cin.tie( 0 );
	ios::sync_with_stdio( false );
	cout << setprecision( 12 ) << fixed;

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

	VS board( H );
	cin >> board;

	int sy, sx, gy, gx;
	REP( i, H )
	{
		REP( j, W )
		{
			if ( board[i][j] == 'S' )
			{
				tie( sy, sx ) = tie( i, j );
			}
			if ( board[i][j] == 'T' )
			{
				tie( gy, gx ) = tie( i, j );
			}
		}
	}

	Dinic maxflow( 2 * H * W );
	const auto in_node = [&]( const int i, const int j ){ return W * i + j; };
	const auto out_node = [&]( const int i, const int j ){ return H * W + in_node( i, j ); };

	REP( i, H )
	{
		REP( j, W )
		{
			if ( board[i][j] != '.' )
			{
				maxflow.connect( in_node( i, j ), out_node( i, j ), 1 );
			}
		}
	}


	{
		VVI rows( H ), columns( W );
		REP( i, H )
		{
			REP( j, W )
			{
				if ( board[i][j] != '.' )
				{
					rows[i].PB( j );
					columns[j].PB( i );
				}
			}
		}

		REP( i, H )
		{
			FOR( j1, rows[i] )
			{
				FOR( j2, rows[i] )
				{
					if ( j1 != j2 )
					{
						maxflow.connect( out_node( i, j1 ), in_node( i, j2 ), INF );
					}
				}
			}
		}
		REP( j, W )
		{
			FOR( i1, columns[j] )
			{
				FOR( i2, columns[j] )
				{
					if ( i1 != i2 )
					{
						maxflow.connect( out_node( i1, j ), in_node( i2, j ), INF );
					}
				}
			}
		}
	}

	const int res = maxflow.solve( out_node( sy, sx ), in_node( gy, gx ) );
	cout << ( INF <= res ? -1 : res ) << endl;

	return 0;
}


Measured memory_bytes: 61824