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.Linq;
using CompLib.Util;
using System.Threading;
using CompLib.Graph;
using System.Collections.Generic;

public class Program
{

    public void Solve()
    {
        var sc = new Scanner();
        int n = sc.NextInt();
        int m = sc.NextInt();

        string[] s = new string[n];
        for (int i = 0; i < n; i++)
        {
            s[i] = sc.Next();
        }

        var mf = new MaxFlow(1 + n * m + 1);
        var ls = new List<int>();
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                int cur = i * m + j + 1;
                if (s[i][j] != '.') continue;
                if ((i + j) % 2 == 0)
                {
                    mf.AddEdge(0, cur, 1);
                }
                else
                {
                    mf.AddEdge(cur, n * m + 1, 1);
                }

                if (i + 1 < n && s[i + 1][j] == '.')
                {
                    int d = (i + 1) * m + j + 1;
                    if ((i + j) % 2 == 0)
                    {
                        ls.Add(mf.AddEdge(cur, d, 1));
                    }
                    else
                    {
                        ls.Add(mf.AddEdge(d, cur, 1));
                    }
                }

                if (j + 1 < m && s[i][j + 1] == '.')
                {
                    int r = i * m + j + 2;
                    if ((i + j) % 2 == 0)
                    {
                        ls.Add(mf.AddEdge(cur, r, 1));
                    }
                    else
                    {
                        ls.Add(mf.AddEdge(r, cur, 1));
                    }
                }
            }
        }
        var ans = new char[n][];
        for (int i = 0; i < n; i++)
        {
            ans[i] = s[i].ToCharArray();
        }
        Console.WriteLine(mf.Flow(0, n * m + 1));
        foreach (var e in ls)
        {
            var edge = mf.GetEdge(e);
            if (edge.Flow < edge.Cap) continue;
            int f = edge.From;
            int t = edge.To;
            if (f > t) (f, t) = (t, f);
            int i = (f - 1) / m;
            int j = (f - 1) % m;
            if (f + 1 == t && j + 1 < m)
            {
                ans[i][j] = '>';
                ans[i][j + 1] = '<';
            }
            else
            {
                ans[i][j] = 'v';
                ans[i + 1][j] = '^';
            }
        }

        for (int i = 0; i < n; i++)
        {
            Console.WriteLine(new string(ans[i]));
        }
    }

    public static void Main(string[] args) => new Program().Solve();
    // public static void Main(string[] args) => new Thread(new Program().Solve, 1 << 27).Start();
}



namespace CompLib.Graph
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using Cap = System.Int32;
    class MaxFlow
    {
        private List<S> _pos;
        private List<InternalEdge>[] _g;
        private readonly int _n;
        private readonly int[] _level, _iter;

        private readonly int[] _queue;
        private int _begin, _end;
        public MaxFlow(int n)
        {
            _n = n;
            _g = new List<InternalEdge>[_n];
            for (int i = 0; i < _n; i++)
            {
                _g[i] = new List<InternalEdge>();
            }
            _pos = new List<S>();

            _level = new int[_n];
            _iter = new int[_n];

            _queue = new int[_n];
        }

        public int AddEdge(int from, int to, Cap cap)
        {
            Debug.Assert(0 <= from && from < _n);
            Debug.Assert(0 <= to && to < _n);
            Debug.Assert(0 <= cap);
            int m = _pos.Count;
            _pos.Add(new S(from, _g[from].Count));
            int fromID = _g[from].Count;
            int toID = _g[to].Count;
            if (from == to) toID++;
            _g[from].Add(new InternalEdge(to, toID, cap));
            _g[to].Add(new InternalEdge(from, fromID, 0));
            return m;
        }

        public Edge GetEdge(int i)
        {
            int m = _pos.Count;
            Debug.Assert(0 <= i && i < m);
            var e = _g[_pos[i].From][_pos[i].Index];
            var re = _g[e.To][e.Rev];

            return new Edge(_pos[i].From, e.To, e.Cap + re.Cap, re.Cap);
        }

        public Edge[] Edges()
        {
            int m = _pos.Count;
            Edge[] result = new Edge[m];
            for (int i = 0; i < m; i++)
            {
                result[i] = GetEdge(i);
            }
            return result;
        }

        public void ChangeEdge(int i, Cap newCap, Cap newFlow)
        {
            int m = _pos.Count;
            Debug.Assert(0 <= i && i < m);
            Debug.Assert(0 <= newFlow && newFlow <= newCap);
            var e = _g[_pos[i].From][_pos[i].Index];
            var re = _g[e.To][e.Rev];
            e.Cap = newCap - newFlow;
            re.Cap = newFlow;
            _g[_pos[i].From][_pos[i].Index] = e;
            _g[e.To][e.Rev] = re;
        }

        private void BFS(int s, int t)
        {
            for (int i = 0; i < _n; i++)
            {
                _level[i] = -1;
            }
            _level[s] = 0;
            _begin = 0;
            _end = 0;
            _queue[_end++] = s;
            while (_end > _begin)
            {
                int v = _queue[_begin++];
                foreach (var e in _g[v])
                {
                    if (e.Cap == 0 || _level[e.To] >= 0) continue;
                    _level[e.To] = _level[v] + 1;
                    if (e.To == t) return;
                    _queue[_end++] = e.To;
                }
            }
        }

        private Cap DFS(int v, int s, Cap up)
        {
            if (v == s) return up;
            Cap res = 0;
            for (; _iter[v] < _g[v].Count; _iter[v]++)
            {
                var e = _g[v][_iter[v]];
                if (_level[v] <= _level[e.To] || _g[e.To][e.Rev].Cap == 0) continue;
                Cap d = DFS(e.To, s, Math.Min(up - res, _g[e.To][e.Rev].Cap));
                if (d <= 0) continue;

                e.Cap += d;
                _g[v][_iter[v]] = e;

                var rev = _g[e.To][e.Rev];
                rev.Cap -= d;
                _g[e.To][e.Rev] = rev;
                res += d;
                if (res == up) break;
            }
            return res;
        }

        public Cap Flow(int s, int t, Cap flowLimit)
        {
            Debug.Assert(0 <= s && s < _n);
            Debug.Assert(0 <= t && t < _n);
            Debug.Assert(s != t);


            Cap flow = 0;
            while (flow < flowLimit)
            {
                BFS(s, t);
                if (_level[t] == -1) break;
                for (int i = 0; i < _n; i++)
                {
                    _iter[i] = 0;
                }
                while (flow < flowLimit)
                {
                    Cap f = DFS(t, s, flowLimit - flow);
                    if (f == 0) break;
                    flow += f;
                }
            }

            return flow;
        }


        public Cap Flow(int s, int t)
        {
            return Flow(s, t, Cap.MaxValue);
        }

        public bool[] MinCut(int s)
        {
            bool[] visited = new bool[_n];
            _begin = 0;
            _end = 0;
            _queue[_end++] = s;
            visited[s] = true;
            while (_end > _begin)
            {
                var p = _queue[_begin++];
                foreach (var e in _g[p])
                {
                    if (e.Cap > 0 && !visited[e.To])
                    {
                        visited[e.To] = true;
                        _queue[_end++] = e.To;
                    }
                }
            }
            return visited;
        }

        struct InternalEdge
        {
            public int To, Rev;
            public Cap Cap;
            public InternalEdge(int to, int rev, Cap cap)
            {
                To = to;
                Rev = rev;
                Cap = cap;
            }
        }

        struct S
        {
            public readonly int From, Index;
            public S(int from, int index)
            {
                From = from;
                Index = index;
            }
        }
    }

    public struct Edge
    {
        public readonly int From, To;
        public readonly Cap Cap, Flow;
        public Edge(int from, int to, Cap cap, Cap flow)
        {
            From = from;
            To = to;
            Cap = cap;
            Flow = flow;
        }
    }
}


namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            if (_index >= _line.Length)
            {
                string s;
                do
                {
                    s = Console.ReadLine();
                } while (s.Length == 0);

                _line = s.Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public string ReadLine()
        {
            _index = _line.Length;
            return Console.ReadLine();
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            string s = Console.ReadLine();
            _line = s.Length == 0 ? new string[0] : s.Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}