#[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" ) };
}

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

    let mut flow = Flow::new(h+w+2);
    const INF: u64 = 1 << 60;

    let s = h+w;
    let t = h+w+1;
    let mut s_pos = (0, 0);
    let mut t_pos = (0, 0);
    for y in 0..h {
        for x in 0..w {
            match a[y][x] {
                'o' => {
                    flow.add_edge(y+w, x, 1, 1);
                },
                'S' => {
                    flow.add_edge(s, y+w, INF, 0);
                    flow.add_edge(s, x, INF, 0);
                    s_pos = (y, x);
                },
                'T' => {
                    flow.add_edge(y+w, t, INF, 0);
                    flow.add_edge(x, t, INF, 0);
                    t_pos = (y, x);
                },
                _ => ()
            }
        }
    }
    if s_pos.0 == t_pos.0 || s_pos.1 == t_pos.1 {
        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: 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));
    }
    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