# D - 浮気予防
from collections import deque
from typing import List

Edge = List[int]  # type alias of Edge


class Dinic:
    """Dinic class to solve max-find_max_flow / min-cut problems.
    References:
        https://ikatakos.com/pot/programming_algorithm/graph_theory/maximum_flow
        http://vartkw.hatenablog.com/entry/2016/12/02/002703
    """

    __slots__ = ["_size", "graph", "_depth", "_progress"]

    def __init__(self, size: int) -> None:
        self._size = size
        self.graph: List[List[Edge]] = [[] for _ in range(size)]
        self._depth = [-1] * size
        self._progress = [0] * size

    def add(self, from_: int, to: int, cap: int = 1, is_directed: bool = True) -> None:
        """Add an edge."""
        self.graph[from_].append([to, cap, len(self.graph[to])])
        self.graph[to].append([from_, 0, len(self.graph[from_]) - 1])
        if not is_directed:
            self.add(to, from_, cap)

    def find_max_flow(self, source: int, target: int, inf: int = 1 << 30) -> int:
        """Find the max-find_max_flow from source to target in O(N^{2}M)."""
        flow = 0
        while True:
            self._bfs(source)
            if self._depth[target] < 0:
                break
            self._progress = [0] * self._size
            cur_flow = self._dfs(source, target, inf)
            while cur_flow:
                flow += cur_flow
                cur_flow = self._dfs(source, target, inf)
        return flow

    def _bfs(self, source: int) -> None:
        depth = [-1] * self._size
        depth[source] = 0
        queue = deque([source])
        while queue:
            v = queue.popleft()
            for to, cap, _ in self.graph[v]:
                if cap > 0 > depth[to]:
                    depth[to] = depth[v] + 1
                    queue.append(to)
        self._depth = depth

    def _dfs(self, v: int, target: int, flow: int) -> int:
        if v == target:
            return flow
        v_edges = self.graph[v]
        for i in range(self._progress[v], len(v_edges)):
            self._progress[v] = i
            to, cap, rev = v_edges[i]
            if not cap or self._depth[v] >= self._depth[to]:
                continue
            d = self._dfs(to, target, min(flow, cap))
            if not d:
                continue
            v_edges[i][1] -= d
            self.graph[to][rev][1] += d
            return d
        return 0


def practice2_d():
    # https://atcoder.jp/contests/practice2/tasks/practice2_d
    N, M = map(int, input().split())
    S = [list(input()) for _ in range(N)]
    dc = Dinic(N * M + 2)

    s = N * M
    t = N * M + 1
    for i in range(N):
        for j in range(M):
            if (i + j) % 2 == 0:
                dc.add(s, M * i + j)
            else:
                dc.add(M * i + j, t)

    for i in range(N):
        for j in range(M):
            if j + 1 < M and S[i][j] == "." and S[i][j + 1] == ".":
                u, v = M * i + j, M * i + j + 1
                if (i + j) % 2:
                    u, v = v, u
                dc.add(u, v)
            if i + 1 < N and S[i][j] == "." and S[i + 1][j] == ".":
                u, v = M * i + j, M * (i + 1) + j
                if (i + j) % 2:
                    u, v = v, u
                dc.add(u, v)

    print(dc.find_max_flow(s, t))
    for u in range(N * M + 2):
        for v, cap, _ in dc.graph[u]:
            ui, uj = divmod(u, M)
            vi, vj = divmod(v, M)
            if (
                not (ui + uj) % 2
                and not cap
                and u != s
                and u != t
                and v != s
                and v != t
            ):
                if ui + 1 == vi:
                    S[ui][uj] = "v"
                    S[vi][vj] = "^"
                elif ui == vi + 1:
                    S[ui][uj] = "^"
                    S[vi][vj] = "v"
                elif uj + 1 == vj:
                    S[ui][uj] = ">"
                    S[vi][vj] = "<"
                elif uj == vj + 1:
                    S[ui][uj] = "<"
                    S[vi][vj] = ">"

    for res in S:
        print("".join(res))


if __name__ == "__main__":
    practice2_d()


Measured memory_bytes: 85120