Problem:
Score : 100 points

Problem Statement

You are given a grid of N rows and M columns. The square at the i-th row and j-th column will be denoted as (i,j).
Some of the squares contain an object. All the remaining squares are empty.
The state of the grid is represented by strings S_1,S_2,\cdots,S_N. The square (i,j) contains an object if S_{i,j}= # and is empty if S_{i,j}= ..

Consider placing 1 \times 2 tiles on the grid. Tiles can be placed vertically or horizontally to cover two adjacent empty squares.
Tiles must not stick out of the grid, and no two different tiles may intersect. Tiles cannot occupy the square with an object.

Calculate the maximum number of tiles that can be placed and any configulation that acheives the maximum.

Constraints

1 \leq N \leq 100

1 \leq M \leq 100

S_i is a string with length M consists of # and ..

Input

Input is given from Standard Input in the following format:

N M
S_1
S_2
\vdots
S_N

Output

On the first line, print the maximum number of tiles that can be placed.

On the next N lines, print a configulation that achieves the maximum.
Precisely, output the strings t_1,t_2,\cdots,t_N constructed by the following way.

t_i is initialized to S_i.

For each (i,j), if there is a tile that occupies (i,j) and (i+1,j), change t_{i,j}:=v, t_{i+1,j}:=^.

For each (i,j), if there is a tile that occupies (i,j) and (i,j+1), change t_{i,j}:=>, t_{i,j+1}:=<.

See samples for further information.

You may print any configulation that maximizes the number of tiles.

Sample Input 1

3 3
#..
..#
...

Sample Output 1

3
#><
vv#
^^.

The following output is also treated as a correct answer.

3
#><
v.#
^><

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using static System.Math;
using System.Text;
using System.Threading;
using System.Globalization;
using System.Runtime.CompilerServices;
using Library;

namespace Program
{
    public static class ProblemD
    {
        static bool SAIKI = false;
        static public int numberOfRandomCases = 0;
        static public void MakeTestCase(List<string> _input, List<string> _output, ref Func<string[], bool> _outputChecker)
        {
        }
        static public void Solve()
        {
            var N = NN;
            var M = NN;
            var S = NSList(N);
            var flow = new LIB_Flow(N * M + 2);
            Func<long, long, long> convToVtx = (x, y) => x * M + y;
            Func<long, (long, long)> convToPos = vtx => (vtx / M, vtx % M);
            var startVtx = N * M;
            var goalVtx = startVtx + 1;
            for (var i = 0; i < N; i++)
            {
                for (var j = 0; j < M; j++)
                {
                    if (S[i][j] == '#') continue;
                    if ((i + j) % 2 == 0)
                    {
                        flow.AddPath(startVtx, convToVtx(i, j), 1);
                        if (i > 0 && S[i - 1][j] != '#') flow.AddPath(convToVtx(i, j), convToVtx(i - 1, j), 1);
                        if (j > 0 && S[i][j - 1] != '#') flow.AddPath(convToVtx(i, j), convToVtx(i, j - 1), 1);
                        if (i < N - 1 && S[i + 1][j] != '#') flow.AddPath(convToVtx(i, j), convToVtx(i + 1, j), 1);
                        if (j < M - 1 && S[i][j + 1] != '#') flow.AddPath(convToVtx(i, j), convToVtx(i, j + 1), 1);
                    }
                    else flow.AddPath(convToVtx(i, j), goalVtx, 1);
                }
            }
            var res = flow.Dinic(startVtx, goalVtx);
            Console.WriteLine(res.maxflow);
            var ans = Repeat(0, N).Select(_ => Repeat('.', M).ToArray()).ToArray();
            for (var i = 0; i < N; i++)
            {
                for (var j = 0; j < M; j++)
                {
                    if (S[i][j] == '#') ans[i][j] = '#';
                    else if ((i + j) % 2 == 0)
                    {
                        foreach (var toVtx in res.fromToCost[convToVtx(i, j)].Where(e => e.Value > 0))
                        {
                            if (toVtx.Key >= N * M) continue;
                            var pos = convToPos(toVtx.Key);
                            if (pos.Item1 == i && pos.Item2 < j)
                            {
                                ans[i][pos.Item2] = '>';
                                ans[i][j] = '<';
                            }
                            else if (pos.Item1 == i && pos.Item2 > j)
                            {
                                ans[i][j] = '>';
                                ans[i][pos.Item2] = '<';
                            }
                            else if (pos.Item1 < i && pos.Item2 == j)
                            {
                                ans[pos.Item1][j] = 'v';
                                ans[i][j] = '^';
                            }
                            else
                            {
                                ans[i][j] = 'v';
                                ans[pos.Item1][j] = '^';
                            }
                        }
                    }
                }
            }
            foreach (var item in ans) Console.WriteLine(item.Join());
        }
        class Printer : StreamWriter
        {
            public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } }
            public Printer(Stream stream) : base(stream, new UTF8Encoding(false, true)) { base.AutoFlush = false; }
            public Printer(Stream stream, Encoding encoding) : base(stream, encoding) { base.AutoFlush = false; }
        }
        static LIB_FastIO fastio = new LIB_FastIODebug();
        static public void Main(string[] args) { if (args.Length == 0) { fastio = new LIB_FastIO(); Console.SetOut(new Printer(Console.OpenStandardOutput())); } if (SAIKI) { var t = new Thread(Solve, 134217728); t.Start(); t.Join(); } else Solve(); Console.Out.Flush(); }
        static long NN => fastio.Long();
        static double ND => fastio.Double();
        static string NS => fastio.Scan();
        static long[] NNList(long N) => Repeat(0, N).Select(_ => NN).ToArray();
        static double[] NDList(long N) => Repeat(0, N).Select(_ => ND).ToArray();
        static string[] NSList(long N) => Repeat(0, N).Select(_ => NS).ToArray();
        static long Count<T>(this IEnumerable<T> x, Func<T, bool> pred) => Enumerable.Count(x, pred);
        static IEnumerable<T> Repeat<T>(T v, long n) => Enumerable.Repeat<T>(v, (int)n);
        static IEnumerable<int> Range(long s, long c) => Enumerable.Range((int)s, (int)c);
        static IOrderedEnumerable<T> OrderByRand<T>(this IEnumerable<T> x) => Enumerable.OrderBy(x, _ => xorshift);
        static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> x) => Enumerable.OrderBy(x.OrderByRand(), e => e);
        static IOrderedEnumerable<T1> OrderBy<T1, T2>(this IEnumerable<T1> x, Func<T1, T2> selector) => Enumerable.OrderBy(x.OrderByRand(), selector);
        static IOrderedEnumerable<T> OrderByDescending<T>(this IEnumerable<T> x) => Enumerable.OrderByDescending(x.OrderByRand(), e => e);
        static IOrderedEnumerable<T1> OrderByDescending<T1, T2>(this IEnumerable<T1> x, Func<T1, T2> selector) => Enumerable.OrderByDescending(x.OrderByRand(), selector);
        static IOrderedEnumerable<string> OrderBy(this IEnumerable<string> x) => x.OrderByRand().OrderBy(e => e, StringComparer.OrdinalIgnoreCase);
        static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> x, Func<T, string> selector) => x.OrderByRand().OrderBy(selector, StringComparer.OrdinalIgnoreCase);
        static IOrderedEnumerable<string> OrderByDescending(this IEnumerable<string> x) => x.OrderByRand().OrderByDescending(e => e, StringComparer.OrdinalIgnoreCase);
        static IOrderedEnumerable<T> OrderByDescending<T>(this IEnumerable<T> x, Func<T, string> selector) => x.OrderByRand().OrderByDescending(selector, StringComparer.OrdinalIgnoreCase);
        static string Join<T>(this IEnumerable<T> x, string separator = "") => string.Join(separator, x);
        static uint xorshift { get { _xsi.MoveNext(); return _xsi.Current; } }
        static IEnumerator<uint> _xsi = _xsc();
        static IEnumerator<uint> _xsc() { uint x = 123456789, y = 362436069, z = 521288629, w = (uint)(DateTime.Now.Ticks & 0xffffffff); while (true) { var t = x ^ (x << 11); x = y; y = z; z = w; w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); yield return w; } }
    }
}
namespace Library {
    class LIB_Dict<K, V> : Dictionary<K, V>
    {
        Func<K, V> d;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_Dict(Func<K, V> _d) { d = _d; }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_Dict() : this(_ => default(V)) { }
        new public V this[K i]
        {
            get
            {
                return TryGetValue(i, out var v) ? v : base[i] = d(i);
            }
            set
            {
                base[i] = value;
            }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override int GetHashCode()
        {
            unchecked
            {
                var ret = 23;
                for (var e = GetEnumerator(); e.MoveNext();) ret = (ret * 37) ^ (e.Current.Key.GetHashCode() << 5 + e.Current.Key.GetHashCode()) ^ e.Current.Value.GetHashCode();
                return ret;
            }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override bool Equals(object obj)
        {
            var o = (LIB_Dict<K, V>)obj;
            foreach (var kv in o)
            {
                if (!ContainsKey(kv.Key) || !this[kv.Key].Equals(kv.Value))
                    return false;
            }
            return o.Count == Count;
        }
    }
    class LIB_Flow
    {
        LIB_Dict<int, long>[] path;
        int N;
        public class FlowResult
        {
            public long maxflow;
            public LIB_Dict<int, long>[] fromToCost;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_Flow(long n)
        {
            N = (int)n;
            path = Enumerable.Repeat(0, N).Select(_ => new LIB_Dict<int, long>()).ToArray();
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddPath(long a, long b, long c)
        {
            path[a][(int)b] += c;
            path[b][(int)a] += 0;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public FlowResult FordFulkerson(long s, long t)
        {
            var f = Enumerable.Repeat(0, N).Select(_ => new LIB_Dict<int, long>()).ToArray();
            for (var i = 0; i < N; i++) foreach (var item in path[i]) f[i][item.Key] = item.Value;
            var done = new long[N];
            var counter = 1L;
            Func<int, long, long> dfs = null;
            dfs = (vtx, c) =>
            {
                done[vtx] = counter;
                if (vtx == t) return c;
                foreach (var item in f[vtx])
                {
                    if (done[item.Key] == counter) continue;
                    if (item.Value == 0) continue;
                    var flow = dfs(item.Key, Min(c, item.Value));
                    if (flow == 0) continue;
                    f[vtx][item.Key] -= flow;
                    f[item.Key][vtx] += flow;
                    return flow;
                }
                return 0;
            };
            var sum = 0L;
            for (long flow; (flow = dfs((int)s, long.MaxValue)) > 0; ++counter) sum += flow;
            for (var i = 0; i < path.Length; i++) foreach (var to in path[i]) f[i][to.Key] = to.Value - f[i][to.Key];
            return new FlowResult { maxflow = sum, fromToCost = f };
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public FlowResult Dinic(long s, long t)
        {
            var f = Enumerable.Repeat(0, N).Select(_ => new LIB_Dict<int, long>()).ToArray();
            for (var i = 0; i < N; i++) foreach (var item in path[i]) f[i][item.Key] = item.Value;
            var pathList = f.Select(e => e.Keys.ToArray()).ToArray();
            var level = new int[N];
            Func<bool> reset = () =>
            {
                level = new int[N];
                var q = new Queue<int>();
                level[s] = 1;
                q.Enqueue((int)s);
                while (q.Count > 0)
                {
                    var v = q.Dequeue();
                    foreach (var item in f[v])
                    {
                        if (item.Value > 0 && level[item.Key] == 0)
                        {
                            level[item.Key] = level[v] + 1;
                            q.Enqueue(item.Key);
                        }
                    }
                }
                return true;
            };
            Func<int, long, long> dfs = null;
            var itr = new int[N];
            dfs = (vtx, c) =>
            {
                if (vtx == t) return c;
                for (; itr[vtx] < pathList[vtx].Length; ++itr[vtx])
                {
                    var pathInfo = pathList[vtx][itr[vtx]];
                    var cap = f[vtx][pathInfo];
                    if (cap > 0 && level[vtx] < level[pathInfo])
                    {
                        var flow = dfs(pathInfo, Min(c, cap));
                        if (flow == 0) continue;
                        f[vtx][pathInfo] -= flow;
                        f[pathInfo][vtx] += flow;
                        return flow;
                    }
                }
                return 0;
            };
            var sum = 0L;
            while (reset() && level[t] > 0)
            {
                itr = new int[N];
                for (long flow; (flow = dfs((int)s, long.MaxValue)) > 0;) sum += flow;
            }
            for (var i = 0; i < path.Length; i++) foreach (var to in path[i]) f[i][to.Key] = to.Value - f[i][to.Key];
            return new FlowResult { maxflow = sum, fromToCost = f };
        }
    }
    class LIB_FastIO
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_FastIO() { str = Console.OpenStandardInput(); }
        readonly Stream str;
        readonly byte[] buf = new byte[1024];
        int len, ptr;
        public bool isEof = false;
        public bool IsEndOfStream
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get { return isEof; }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        byte read()
        {
            if (isEof) throw new EndOfStreamException();
            if (ptr >= len)
            {
                ptr = 0;
                if ((len = str.Read(buf, 0, 1024)) <= 0)
                {
                    isEof = true;
                    return 0;
                }
            }
            return buf[ptr++];
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        char Char()
        {
            byte b = 0;
            do b = read();
            while (b < 33 || 126 < b);
            return (char)b;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        virtual public string Scan()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b >= 33 && b <= 126; b = (char)read())
                sb.Append(b);
            return sb.ToString();
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        virtual public long Long()
        {
            long ret = 0; byte b = 0; var ng = false;
            do b = read();
            while (b != '-' && (b < '0' || '9' < b));
            if (b == '-') { ng = true; b = read(); }
            for (; true; b = read())
            {
                if (b < '0' || '9' < b)
                    return ng ? -ret : ret;
                else ret = ret * 10 + b - '0';
            }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        virtual public double Double() { return double.Parse(Scan(), CultureInfo.InvariantCulture); }
    }
    class LIB_FastIODebug : LIB_FastIO
    {
        Queue<string> param = new Queue<string>();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        string NextString() { if (param.Count == 0) foreach (var item in Console.ReadLine().Split(' ')) param.Enqueue(item); return param.Dequeue(); }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_FastIODebug() { }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override string Scan() => NextString();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override long Long() => long.Parse(NextString());
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override double Double() => double.Parse(NextString());
    }
}