macro_rules! read_line_to_tuple {
    ( $( $t:ty ),* ) => {{
        let mut input = String::new();
        std::io::stdin().read_line(&mut input).unwrap();
        let mut iter = input.split_whitespace();
        ( $( iter.next().unwrap().parse::<$t>().unwrap() ),* )
    }};
}

use std::collections::VecDeque;
use std::cmp;

#[derive(Clone, Copy)]
struct Edge {
    to: usize, rev: usize, cap: i64,
}

impl Edge {
    fn new(to: usize, rev: usize, cap: i64) -> Edge {
        Edge { to, rev, cap, }
    }
}

struct Dinic {
    g: Vec<Vec<Edge>>,
    level: Vec<i32>,
    iter: Vec<usize>,
    que: VecDeque<usize>,
}

impl Dinic {
    fn new(n: usize) -> Dinic {
        Dinic {
            g: vec![vec![]; n],
            level: vec![0; n],
            iter: vec![0; n],
            que: VecDeque::with_capacity(n),
        }
    }

    fn add_edge(&mut self, from: usize, to: usize, cap: i64) {
        let rev = self.g[to].len();
        self.g[from].push(Edge::new(to, rev, cap));
        let rev = self.g[from].len() - 1;
        self.g[to].push(Edge::new(from, rev, 0));
    }

    fn bfs(&mut self, s: usize, t: usize) {
        self.level.iter_mut().for_each(|e| *e = -1);
        self.level[s] = 0;
        self.que.clear();
        self.que.push_back(s);
        while let Some(v) = self.que.pop_front() {
            for e in &self.g[v] {
                if e.cap == 0 || self.level[e.to] >= 0 { continue; }
                self.level[e.to] = self.level[v] + 1;
                if e.to == t { return; }
                self.que.push_back(e.to);
            }
        }
    }

    fn dfs(&mut self, s: usize, v: usize, up: i64) -> i64 {
        if v == s { return up; }
        let mut res = 0;
        for i in self.iter[v]..self.g[v].len() {
            self.iter[v] = i;
            let e = self.g[v][i];
            if self.level[v] <= self.level[e.to] { continue; }
            if self.g[e.to][e.rev].cap == 0 { continue; }
            let d = {
                let up = cmp::min(up - res, self.g[e.to][e.rev].cap);
                self.dfs(s, e.to, up)
            };
            if d <= 0 { continue; }
            self.g[v][i].cap += d;
            self.g[e.to][e.rev].cap -= d;
            res += d;
            if res == up { return res; }
        }
        self.iter[v] = self.g[v].len();
        res
    }

    fn max_flow(&mut self, s: usize, t: usize, flow_limit: i64) -> i64 {
        let mut flow = 0;
        while flow < flow_limit {
            self.bfs(s, t);
            if self.level[t] == -1 { break; }
            self.iter.iter_mut().for_each(|e| *e = 0);
            while flow < flow_limit {
                let f = self.dfs(s, t, flow_limit - flow);
                if f == 0 { break; }
                flow += f;
            }
        }
        flow
    }
}

fn main() {
    let (n, m) = read_line_to_tuple!(usize, usize);
    let mut grid: Vec<Vec<char>> = {
        (0..n)
            .map(|_| read_line_to_tuple!(String).chars().collect())
            .collect()
    };

    let mut dinic = Dinic::new(n * m + 2);
    let (s, t) = (n * m, n * m + 1);

    for i in 0..n {
        for j in 0..m {
            if grid[i][j] == '#' { continue; }
            let v = i * m + j;
            if (i + j) % 2 == 0 {
                dinic.add_edge(s, v, 1);
            } else {
                dinic.add_edge(v, t, 1);
            }
        }
    }

    for i in 0..n {
        for j in 0..m {
            if (i + j) % 2 == 1 || grid[i][j] == '#' { continue; }
            let from = i * m + j;
            if i > 0 && grid[i - 1][j] == '.' {
                let to = (i - 1) * m + j;
                dinic.add_edge(from, to, 1);
            }
            if j > 0 && grid[i][j - 1] == '.' {
                let to = i * m + (j - 1);
                dinic.add_edge(from, to, 1);
            }
            if i + 1 < n && grid[i + 1][j] == '.' {
                let to = (i + 1) * m + j;
                dinic.add_edge(from, to, 1);
            }
            if j + 1 < m && grid[i][j + 1] == '.' {
                let to = i * m + (j + 1);
                dinic.add_edge(from, to, 1);
            }
        }
    }

    let mut ans = Vec::with_capacity(n + 1);
    ans.push(dinic.max_flow(s, t, std::i64::MAX).to_string());

    for v in 0..(n * m) {
        let (i0, j0) = (v / m, v % m);
        if (i0 + j0) % 2 == 0 { continue; }
        for e in &dinic.g[v] {
            if e.to == t || e.cap == 0 { continue; }
            let (i1, j1) = (e.to / m, e.to % m);
            if i0 < i1 {
                grid[i0][j0] = 'v';
                grid[i1][j1] = '^';
            } else if i0 > i1 {
                grid[i1][j1] = 'v';
                grid[i0][j0] = '^';
            } else if j0 < j1 {
                grid[i0][j0] = '>';
                grid[i1][j1] = '<';
            } else {
                grid[i1][j1] = '>';
                grid[i0][j0] = '<';
            }
        }
    }

    for i in 0..n {
        ans.push(grid[i].iter().collect());
    }
    println!("{}", ans.join("\n"));
}

Measured memory_bytes: 4852