#include <bits/stdc++.h>
#define for_range(i, a, b) for (int i = (a); i < (b); i++)
#define for_range_rev(i, a, b) for (int i = (b)-1; i >= (a); i++)
using namespace std;
using i64 = int_fast64_t;
using u64 = uint_fast64_t;
using u32 = uint_fast32_t;
const u64 MOD = 1'000'000'007;
// const u64 MOD = 998'244'353;
const int DX4[] = {1, 0, -1, 0};
const int DY4[] = {0, 1, 0, -1};
const int DX8[] = {0, 1, 1, 1, 0, -1, -1, -1};
const int DY8[] = {1, 1, 0, -1, -1, -1, 0, 1};

int ceil_log2(int n) {
    int x = 0;
    while ((1u << x) < (u32)(n)) x++;
    return x;
}

struct maxflow {
    using C = i64;

    maxflow() : n(0) {}
    maxflow(int sz) : n(sz), g(n) {}

    struct edge {
        int from, to;
        C cap, flow;
    };
    struct E {
        int t, r;
        C c;
    };
    int n;
    vector<pair<int, int>> p;
    vector<vector<E>> g;

    int add_edge(int u, int v, C c) {
        assert(0 <= u && u < n);
        assert(0 <= v && v < n);
        assert(0 <= c);
        int m = p.size();
        p.push_back({u, int(g[u].size())});
        g[u].push_back(E{v, int(g[v].size()), c});
        g[v].push_back(E{u, int(g[u].size()) - 1, 0});
        return m;
    }

    edge get_edge(int i) {
        int m = p.size();
        assert(0 <= i && i < m);
        auto e = g[p[i].first][p[i].second];
        auto re = g[e.t][e.r];
        return edge{p[i].first, e.t, e.c + re.c, re.c};
    }

    vector<edge> edges() {
        int m = p.size();
        vector<edge> r;
        for_range(i, 0, m) r.push_back(get_edge(i));
        return r;
    }

    void change_edge(int i, C nc, C nf) {
        int m = p.size();
        assert(0 <= i && i < m);
        assert(0 <= nf && nf <= nc);
        auto& e = g[p[i].first][p[i].second];
        auto& re = g[e.t][e.r];
        e.c = nc - nf;
        re.c = nf;
    }

    C flow(int s, int t) { return flow(s, t, numeric_limits<C>::max()); }
    C flow(int s, int t, C lim) {
        assert(0 <= s && s < n);
        assert(0 <= t && t < n);
        vector<int> l(n), a(n);
        queue<int> q;
        auto b = [&]() {
            fill(l.begin(), l.end(), -1);
            l[s] = 0;
            queue<int>().swap(q);
            q.push(s);
            while (!q.empty()) {
                int v = q.front();
                q.pop();
                for (auto e : g[v]) {
                    if (e.c == 0 || l[e.t] >= 0) continue;
                    l[e.t] = l[v] + 1;
                    if (e.t == t) return;
                    q.push(e.t);
                }
            }
        };
        auto d = [&](auto m, int v, C u) {
            if (v == s) return u;
            C r = 0;
            int x = l[v];
            for (int& i = a[v]; i < int(g[v].size()); i++) {
                E& e = g[v][i];
                if (x <= l[e.t] || g[e.t][e.r].c == 0) continue;
                C d = m(m, e.t, min(u - r, g[e.t][e.r].c));
                if (d <= 0) continue;
                g[v][i].c += d;
                g[e.t][e.r].c -= d;
                r += d;
                if (r == u) break;
            }
            return r;
        };
        C f = 0;
        while (f < lim) {
            b();
            if (l[t] == -1) break;
            fill(a.begin(), a.end(), 0);
            while (f < lim) {
                C g = d(d, t, lim - f);
                if (!g) break;
                f += g;
            }
        }
        return f;
    }

    vector<bool> min_cut(int s) {
        vector<bool> v(n);
        queue<int> q;
        q.push(s);
        while (!q.empty()) {
            int p = q.front();
            q.pop();
            v[p] = true;
            for (auto e : g[p]) {
                if (e.c && !v[e.t]) {
                    v[e.t] = true;
                    q.push(e.t);
                }
            }
        }
        return v;
    }
};

int main() {
    int h, w;
    cin >> h >> w;
    vector<string> S(h);
    for (auto& x : S) cin >> x;

    maxflow g(h * w + 2);
    int s = h * w, t = h * w + 1;
    auto id = [&](int i, int j) { return i * w + j; };

    for_range(i, 0, h) for_range(j, 0, w) {
        if (S[i][j] == '#') continue;
        if ((i + j) % 2 == 0) {
            g.add_edge(id(i, j), t, 1);
            continue;
        }
        g.add_edge(s, id(i, j), 1);
        for_range(k, 0, 4) {
            int x = i + DX4[k], y = j + DY4[k];
            if (x < 0 || h <= x || y < 0 || w <= y) continue;
            if (S[x][y] == '#') continue;
            g.add_edge(id(i, j), id(x, y), 1);
        }
    }

    cout << g.flow(s, t) << '\n';
    vector<maxflow::edge> edges = g.edges();

    for (auto e : edges) {
        if (e.flow == 0 || e.from == s || e.to == t) continue;
        pair<int, int> a(e.from / w, e.from % w);
        pair<int, int> b(e.to / w, e.to % w);
        if (a > b) swap(a, b);
        if (a.first + 1 == b.first) {
            S[a.first][a.second] = 'v';
            S[b.first][b.second] = '^';
        } else {
            S[a.first][a.second] = '>';
            S[b.first][b.second] = '<';
        }
    }

    for (auto x : S) cout << x << '\n';
}

Measured memory_bytes: 6324