# -*- coding: utf-8 -*-
import bisect
import heapq
import math
import random
from collections import Counter, defaultdict, deque
from decimal import ROUND_CEILING, ROUND_HALF_UP, Decimal
from fractions import Fraction
from functools import lru_cache, reduce
from itertools import combinations, combinations_with_replacement, product, permutations, accumulate
from operator import add, mul, sub, itemgetter, attrgetter
import queue

import sys
# sys.setrecursionlimit(10**6)
# readline = sys.stdin.buffer.readline
readline = sys.stdin.readline

INF = 2**62-1


def read_int():
    return int(readline())


def read_int_n():
    return list(map(int, readline().split()))


def read_float():
    return float(readline())


def read_float_n():
    return list(map(float, readline().split()))


def read_str():
    return readline().strip()


def read_str_n():
    return readline().strip().split()


def ep(*args):
    print(*args, file=sys.stderr)


def mt(f):
    import time

    def wrap(*args, **kwargs):
        s = time.perf_counter()
        ret = f(*args, **kwargs)
        e = time.perf_counter()

        ep(e - s, 'sec')
        return ret

    return wrap


class Dinic:
    def __init__(self, v):
        self.V = v
        self.G = [list() for _ in range(v)]
        self.level = [0 for _ in range(v)]
        self.iter = [0 for _ in range(v)]
        self.pos = []

    def add_edge(self, from_, to, cap):
        self.pos.append((from_, len(self.G[from_])))
        # to: 行き先, cap: 容量, rev: 反対側の辺
        # 0           1          2
        self.G[from_].append([to, cap, len(self.G[to])])
        self.G[to].append([from_, 0, len(self.G[from_])-1])


    def edges(self):
        es = []
        for f, t in self.pos:
            e = self.G[f][t]
            re = self.G[e[0]][e[2]]
            # from, to, cap, flow
            e = [f, e[0], e[1] + re[1], re[1]]
            es.append(e)
        return es

    # sからの最短距離をbfsで計算
    def bfs(self, s):
        self.level = [-1 for _ in range(self.V)]
        self.level[s] = 0
        que = queue.Queue()
        que.put(s)
        while not que.empty():
            v = que.get()
            for i in range(len(self.G[v])):
                e = self.G[v][i]
                if e[1] > 0 and self.level[e[0]] < 0:
                    self.level[e[0]] = self.level[v] + 1
                    que.put(e[0])

    # 増加バスをdfsで探す
    def dfs(self, v, t, f):
        if v == t:
            return f
        for i in range(self.iter[v], len(self.G[v])):
            self.iter[v] = i
            e = self.G[v][i]
            if e[1] > 0 and self.level[v] < self.level[e[0]]:
                d = self.dfs(e[0], t, min(f, e[1]))
                if d > 0:
                    e[1] -= d
                    self.G[e[0]][e[2]][1] += d
                    return d

        return 0

    def max_flow(self, s, t):
        flow = 0
        while True:
            self.bfs(s)
            # bfsで到達不可
            if self.level[t] < 0:
                return flow
            self.iter = [0 for _ in range(self.V)]
            f = self.dfs(s, t, INF)
            while f > 0:
                flow += f
                f = self.dfs(s, t, INF)


@mt
def slv(N, M, S):
    S = [list(s) for s in S]
    g = Dinic(N*M+2)
    s = N*M
    t = s + 1

    for i in range(N):
        for j in range(M):
            if S[i][j] == '#':
                continue
            v = i*M + j
            if (i + j )%2 == 0:
                g.add_edge(s, v, 1)
            else:
                g.add_edge(v, t, 1)

    for i in range(N):
        for j in range(M):
            if S[i][j] == '#':
                continue
            if (i+j) % 2 == 1:
                continue
            v0 = i*M + j
            for x, y in [(i-1, j), (i+1, j), (i, j-1), (i, j+1)]:
                if not (0 <= x < N and 0 <= y < M):
                    continue
                v1 = x*M + y
                g.add_edge(v0, v1, 1)

    print(g.max_flow(s, t))
    for from_, to, _, flow in g.edges():
        if from_ in {s, t} or to in {s, t} or flow == 0:
            continue
        i0 = from_ // M
        j0 = from_ % M
        i1 = to // M
        j1 = to % M

        if i0 == i1+1:
            S[i1][j1] = 'v'
            S[i0][j0] = '^'
        elif j0 == j1+1:
            S[i1][j1] = '>'
            S[i0][j0] = '<'
        elif i0 == i1-1:
            S[i1][j1] = '^'
            S[i0][j0] = 'v'
        else:
            S[i1][j1] = '<'
            S[i0][j0] = '>'

    for s in S:
        print(''.join(s))


def main():
    N, M = read_int_n()
    S = [read_str() for _ in range(N)]
    slv(N, M, S)


if __name__ == '__main__':
    main()


Measured memory_bytes: 101336