#[allow(unused_macros)]
macro_rules! input {
    ( source = $ s : expr , $ ( $ r : tt ) * ) => { let mut iter = $ s . split_whitespace ( ) ; let mut next = || { iter . next ( ) . unwrap ( ) } ; input_inner ! { next , $ ( $ r ) * } };
    ( $ ( $ r : tt ) * ) => { let stdin = std :: io :: stdin ( ) ; let mut bytes = std :: io :: Read :: bytes ( std :: io :: BufReader :: new ( stdin . lock ( ) ) ) ; let mut next = move || -> String { bytes . by_ref ( ) . map ( | r | r . unwrap ( ) as char ) . skip_while ( | c | c . is_whitespace ( ) ) . take_while ( | c |! c . is_whitespace ( ) ) . collect ( ) } ; input_inner ! { next , $ ( $ r ) * } };
}
#[allow(unused_macros)]
macro_rules! input_inner {
    ( $ next : expr ) => { };
    ( $ next : expr , ) => { };
    ( $ next : expr , $ var : ident : $ t : tt $ ( $ r : tt ) * ) => { let $ var = read_value ! ( $ next , $ t ) ; input_inner ! { $ next $ ( $ r ) * } };
}
#[allow(unused_macros)]
macro_rules! read_value {
    ( $ next : expr , ( $ ( $ t : tt ) ,* ) ) => { ( $ ( read_value ! ( $ next , $ t ) ) ,* ) };
    ( $ next : expr , [ $ t : tt ; $ len : expr ] ) => { ( 0 ..$ len ) . map ( | _ | read_value ! ( $ next , $ t ) ) . collect ::< Vec < _ >> ( ) };
    ( $ next : expr , chars ) => { read_value ! ( $ next , String ) . chars ( ) . collect ::< Vec < char >> ( ) };
    ( $ next : expr , usize1 ) => { read_value ! ( $ next , usize ) - 1 };
    ( $ next : expr , $ t : ty ) => { $ next ( ) . parse ::<$ t > ( ) . expect ( "Parse error" ) };
}

#[allow(unused_macros)]
macro_rules! map {
    ( ) => { IndexMap ( std :: collections :: HashMap :: new ( ) ) };
    ( $ value : expr ; $ ( $ key : expr ) ,* ) => { IndexMap ( vec ! [ $ ( $ key ) ,* ] . into_iter ( ) . map ( | k | ( k , $ value ) ) . collect ::< std :: collections :: HashMap < _ , _ >> ( ) ) };
    ( $ value : expr ; $ ( $ ( $ key : expr ) ,* ) ;* ) => { map ! ( $ ( $ ( $ key ) ,* ) ;* => $ value ) };
    ( $ ( $ head : expr ) ,*; $ ( $ ( $ tail : expr ) ,* ) ;* => $ init : expr ) => { map ! [ map ! ( $ ( $ ( $ tail ) ,* ) ;* => $ init ) ; $ ( $ head ) ,* ] };
    ( $ ( $ head : expr ) ,* => $ init : expr ) => { map ! [ $ init ; $ ( $ head ) ,* ] };
}
#[derive(Debug, Clone)]
struct IndexMap<K: Eq + std::hash::Hash, V>(pub std::collections::HashMap<K, V>);
#[allow(dead_code)]
impl<K: Eq + std::hash::Hash + std::clone::Clone, V> IndexMap<K, V> {
    fn keys_vec(&self) -> Vec<K> {
        self.keys().cloned().collect()
    }
}
#[allow(dead_code)]
impl<K, V> std::ops::Deref for IndexMap<K, V>
where
    K: Eq + std::hash::Hash,
{
    type Target = std::collections::HashMap<K, V>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
#[allow(dead_code)]
impl<'a, K, V, Q: ?Sized> std::ops::Index<&'a Q> for IndexMap<K, V>
where
    K: std::borrow::Borrow<Q> + Eq + std::hash::Hash,
    Q: Ord + Eq + std::hash::Hash,
{
    type Output = V;
    fn index(&self, index: &Q) -> &V {
        self.0.get(index).expect("no entry found for key")
    }
}
#[allow(dead_code)]
impl<'a, K, V> std::ops::IndexMut<&'a K> for IndexMap<K, V>
where
    K: Ord + Eq + std::hash::Hash + Clone,
    V: Default,
{
    fn index_mut(&mut self, index: &K) -> &mut V {
        self.0.entry(index.clone()).or_insert(Default::default());
        self.0.get_mut(index).expect("no entry found for key")
    }
}

fn main() {
    input! {
        h: usize,
        w: usize,
        a: [chars; h],
    }

    let mut vindex = map![];
    let mut cnt = 0;
    let mut s = 0;
    let mut t = 0;
    let mut sx = 0;
    let mut sy = 0;
    let mut tx = 0;
    let mut ty = 0;
    for y in 0..h {
        vindex[&(Some(y), None)] = cnt;
        cnt += 1;
    }
    for x in 0..w {
        vindex[&(None, Some(x))] = cnt;
        cnt += 1;
    }
    let mut flow = Flow::new(cnt+2);
    for y in 0..h {
        for x in 0..w {
            match a[y][x] {
                'o' => {
                    flow.add_edge(vindex[&(Some(y), None)], vindex[&(None, Some(x))], 1, 1);
                },
                'S' => {
                    sx = x;
                    sy = y;
                    s = cnt;
                    cnt += 1;
                    flow.add_edge(s, vindex[&(Some(y), None)], 1u64 << 60, 0);
                    flow.add_edge(s, vindex[&(None, Some(x))], 1u64 << 60, 0);
                },
                'T' => {
                    tx = x;
                    ty = y;
                    t = cnt;
                    cnt += 1;
                    flow.add_edge(vindex[&(Some(y), None)], t, 1u64 << 60, 0);
                    flow.add_edge(vindex[&(None, Some(x))], t, 1u64 << 60, 0);
                },
                _ => ()
            }
        }
    }

    if sx == tx || sy == ty {
        println!("{}", -1);
    } else {
        println!("{}", flow.max_flow(s, t));
    }
}

#[allow(dead_code)]
#[derive(Debug)]
struct Flow {
    #[doc = " to, rev, capacity"]
    edges: Vec<Vec<(usize, usize, u64)>>,
}
#[allow(dead_code)]
impl Flow {
    pub fn new(n: usize) -> Flow {
        Flow {
            edges: vec![vec![]; n],
        }
    }
    pub fn add_edge(&mut self, from: usize, to: usize, cap: u64, rev_cap: u64) {
        let from_rev = self.edges[to].len();
        let to_rev = self.edges[from].len();
        self.edges[from].push((to, from_rev, cap));
        self.edges[to].push((from, to_rev, rev_cap));
    }
    pub fn max_flow(&mut self, s: usize, t: usize) -> u64 {
        let mut flow = 0;
        loop {
            let level = self.bfs(s);
            let mut iter = vec![0; self.edges.len()];
            if level[t].is_none() {
                return flow;
            }
            loop {
                let f = self.dfs(s, t, u64::max_value(), &level, &mut iter);
                if f == 0 {
                    break;
                }
                flow += f;
            }
        }
    }
    fn bfs(&self, s: usize) -> Vec<Option<usize>> {
        let mut level = vec![None; self.edges.len()];
        let mut que = std::collections::VecDeque::new();
        level[s] = Some(0);
        que.push_back(s);
        while let Some(v) = que.pop_front() {
            let l = Some(level[v].unwrap() + 1);
            for &(to, _, cap) in &self.edges[v] {
                if cap > 0 && level[to].is_none() {
                    level[to] = l;
                    que.push_back(to);
                }
            }
        }
        level
    }
    fn dfs(
        &mut self,
        v: usize,
        t: usize,
        f: u64,
        level: &[Option<usize>],
        iter: &mut [usize],
    ) -> u64 {
        if v == t {
            return f;
        }
        for i in iter[v]..self.edges[v].len() {
            iter[v] = i;
            let (to, rev, cap) = self.edges[v][i];
            if cap > 0 && level[v].unwrap() < level[to].unwrap_or(0) {
                let d = self.dfs(to, t, std::cmp::min(f, cap), level, iter);
                if d > 0 {
                    self.edges[v][i].2 -= d;
                    self.edges[to][rev].2 += d;
                    return d;
                }
            }
        }
        0
    }
}

Measured memory_bytes: 4352