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 ProblemA
    {
        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_MaxFlow(N * M + 2);
            var startVtx = N * M;
            var goalVtx = startVtx + 1;
            var idx = new int[N, M];
            for (var i = 0; i < N; i++)
            {
                for (var j = 0; j < M; j++)
                {
                    var vtx = i * M + j;
                    if (S[i][j] == '#') continue;
                    if ((i + j) % 2 == 0)
                    {
                        flow.AddEdge(startVtx, vtx, 1);
                        if (i > 0 && S[i - 1][j] != '#') idx[i, j] = flow.AddEdge(vtx, vtx - M, 1);
                        if (j > 0 && S[i][j - 1] != '#') idx[i, j] = flow.AddEdge(vtx, vtx - 1, 1);
                        if (i < N - 1 && S[i + 1][j] != '#') idx[i, j] = flow.AddEdge(vtx, vtx + M, 1);
                        if (j < M - 1 && S[i][j + 1] != '#') idx[i, j] = flow.AddEdge(vtx, vtx + 1, 1);
                    }
                    else flow.AddEdge(vtx, goalVtx, 1);
                }
            }
            var res = flow.Flow(startVtx, goalVtx);
            Console.WriteLine(res);
            var ans = new char[N, M];
            for (var i = 0; i < N; i++)
            {
                for (var j = 0; j < M; j++)
                {
                    ans[i, j] = S[i][j];
                }
            }
            foreach (var item in flow.GetAllEdge())
            {
                if (item.from != startVtx && item.to != goalVtx && item.flow == 1)
                {
                    var fx = item.from / M;
                    var fy = item.from % M;
                    var tx = item.to / M;
                    var ty = item.to % M;
                    if (fx > tx)
                    {
                        ans[tx, ty] = 'v';
                        ans[fx, fy] = '^';
                    }
                    else if (fx < tx)
                    {
                        ans[fx, fy] = 'v';
                        ans[tx, ty] = '^';
                    }
                    else if (fy < ty)
                    {
                        ans[fx, fy] = '>';
                        ans[tx, ty] = '<';
                    }
                    else
                    {
                        ans[fx, fy] = '<';
                        ans[tx, ty] = '>';
                    }
                }
            }
            for (var i = 0; i < N; i++)
            {
                for (var j = 0; j < M; j++)
                {
                    Console.Write(ans[i, j]);
                }
                Console.WriteLine();
            }
        }
        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_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());
    }
    class LIB_MaxFlow
    {
        public struct Edge
        {
            public int from;
            public int to;
            public long cap;
            public long flow;
            public long cost;
        }
        public struct CapCost
        {
            public long cap;
            public long cost;
        }
        const int SHIFT_SIZE = 30;
        const int MASK = 1073741823;
        List<ulong> pos;
        List<int>[] gTo;
        List<int>[] gRev;
        List<long>[] gCap;
        int N;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_MaxFlow(long n)
        {
            N = (int)n;
            pos = new List<ulong>();
            gTo = new List<int>[n];
            gRev = new List<int>[n];
            gCap = new List<long>[n];
            for (var i = 0; i < n; i++)
            {
                gTo[i] = new List<int>();
                gRev[i] = new List<int>();
                gCap[i] = new List<long>();
            }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public int AddEdge(long from, long to, long cap)
        {
            var ret = pos.Count;
            pos.Add(((ulong)from << SHIFT_SIZE) | (uint)gTo[from].Count);
            gTo[from].Add((int)to);
            gRev[from].Add(gRev[to].Count);
            gCap[from].Add(cap);
            gTo[to].Add((int)from);
            gRev[to].Add(gRev[from].Count - 1);
            gCap[to].Add(0);
            return ret;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public Edge GetEdge(long i)
        {
            var idx = (int)i;
            var idxf = pos[idx] >> SHIFT_SIZE;
            var idxt = (int)(pos[idx] & MASK);
            var eTo = gTo[idxf][idxt];
            var eRev = gRev[idxf][idxt];
            var reCap = gCap[eTo][eRev];
            return new Edge { from = (int)(pos[idx] >> SHIFT_SIZE), to = eTo, cap = gCap[idxf][idxt] + reCap, flow = reCap };
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public Edge[] GetAllEdge()
        {
            var res = new Edge[pos.Count];
            for (var i = 0; i < res.Length; ++i) res[i] = GetEdge(i);
            return res;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void ChangeEdge(long i, long newCap, long newFlow)
        {
            var idx = (int)i;
            var idxf = pos[idx] >> SHIFT_SIZE;
            var idxt = (int)(pos[idx] & MASK);
            gCap[idxf][idxt] = newCap - newFlow;
            gCap[gTo[idxf][idxt]][gRev[idxf][idxt]] = newFlow;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public long Flow(long s, long t) => Flow(s, t, long.MaxValue >> 2);
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public long Flow(long s, long t, long flowLimit)
        {
            var level = new int[N];
            var iter = new int[N];
            var que = new Queue<int>();
            Func<int, long, long> dfs = null;
            dfs = (v, up) =>
            {
                var res = 0L;
                var levelv = level[v];
                var gToV = gTo[v];
                var gCapV = gCap[v];
                var gRevV = gRev[v];
                for (ref int i = ref iter[v]; i < gToV.Count; ++i)
                {
                    var gToVi = gToV[i];
                    var gRevVi = gRevV[i];
                    var gcap = gCap[gToVi][gRevVi];
                    if (levelv <= level[gToVi] || gcap == 0) continue;
                    var param = Math.Min(up - res, gcap);
                    var d = gToVi == s ? param : dfs(gToVi, param);
                    if (d <= 0) continue;
                    gCapV[i] += d;
                    gCap[gToVi][gRevVi] -= d;
                    res += d;
                    if (res == up) break;
                }
                return res;
            };
            var flow = 0L;
            while (flow < flowLimit)
            {
                for (var i = 0; i < level.Length; ++i) level[i] = -1;
                level[s] = 0;
                que.Enqueue((int)s);
                while (que.Count > 0)
                {
                    var v = que.Dequeue();
                    var gToV = gTo[v];
                    var gCapV = gCap[v];
                    var levelv = level[v] + 1;
                    for (var i = 0; i < gToV.Count; ++i)
                    {
                        var gToVi = gToV[i];
                        if (gCapV[i] == 0 || level[gToVi] >= 0) continue;
                        level[gToVi] = levelv;
                        if (gToVi == t)
                        {
                            que.Clear();
                            break;
                        }
                        que.Enqueue(gToVi);
                    }
                }
                if (level[t] == -1) break;
                iter = new int[N];
                while (flow < flowLimit)
                {
                    var f = t == s ? (flowLimit - flow) : dfs((int)t, flowLimit - flow);
                    if (f == 0) break;
                    flow += f;
                }
            }
            return flow;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool[] MinCut(long s)
        {
            var visited = new bool[N];
            var que = new Queue<int>();
            que.Enqueue((int)s);
            while (que.Count > 0)
            {
                var p = que.Dequeue();
                visited[p] = true;
                var gToP = gTo[p];
                var gCapP = gCap[p];
                for (var i = 0; i < gToP.Count; ++i)
                {
                    var gToPi = gToP[i];
                    if (gCapP[i] > 0 && !visited[gToPi])
                    {
                        visited[gToPi] = true;
                        que.Enqueue(gToPi);
                    }
                }
            }
            return visited;
        }
    }
}