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.Linq;
using System.Text;

//using System.Numerics;
using CS=System.Runtime.CompilerServices;
//using System.Diagnostics;
using static System.Math;
using ll=System.Int64;
using static Contest_D.Lib_IO;
using static Contest_D.Lib_Minifunc;

using C = System.Int32;
using V = System.Int32;

namespace Contest_D {

public static class Entry
{

	public static void Main() {
		checked{



			int n, m;
			Lib_IO.rm(out n, out m);
			string[] s;
			rl(n,out s);

			Dinic flow = new Dinic(n*m+2);
			for (int i = 0; i < n; i++)
			{
				for (int j = 0; j < m; j++)
				{
					int k= i*m+j;
					if(s[i][j]=='#') continue;
					if((i+j)%2==0){
						flow.AddDirectedEdge(n*m,k,1);
						if(j<m-1 && s[i][j+1]=='.'){
							flow.AddDirectedEdge(k,k+1,1);
						}
						if(i<n-1 && s[i+1][j]=='.'){
							flow.AddDirectedEdge(k,k+m,1);
						}
						if(0<j && s[i][j-1]=='.'){
							flow.AddDirectedEdge(k,k-1,1);
						}
						if(0<i && s[i-1][j]=='.'){
							flow.AddDirectedEdge(k,k-m,1);
						}
					}
					else flow.AddDirectedEdge(k,n*m+1,1);
				}
			}
			char[][] ans = new char[n][];
			for (int i = 0; i < n; i++)
			{
				ans[i] = s[i].ToCharArray();
			}
			int cnt = flow.Execute(n*m,n*m+1);
			for (int i = 0; i < n; i++)
			{
				for (int j = 0; j < m; j++)
				{
					int k= i*m+j;
					if((i+j)%2==1) continue;
					foreach (var e in flow.GetEdges(k))
					{
						if(e.Item2<n*m&&0<e.Item4){
							ll ni = e.Item2/m;
							ll nj = e.Item2%m;
							if(i==ni) {
								ans[i][Min(j,nj)] = '>';
								ans[i][Max(j,nj)] = '<';
								break;
							}
							else if(j==nj) {
								ans[Min(i,ni)][j] = 'v';
								ans[Max(i,ni)][j] = '^';
								break;
							}
						}
					} 
				}
			}			

			Lib_IO.wm(cnt);
			Lib_IO.wg(ans);
		}
	}


public class Dinic {
	public readonly List<Edge>[] G;
	readonly int[] lv, iter;
	/// <summary>
	/// 頂点数 <paramref name="V"/> で辺が存在しないグラフを構築します．
	/// </summary>
	/// <param name="V">頂点の数</param>
	/// <remarks>この操作は O(<paramref name="V"/>) で実行されます．</remarks>
	public Dinic(int V) {
		G = new List<Edge>[V];
		lv = new int[V];
		iter = new int[V];
		for (int i = 0; i < G.Length; i++)
			G[i] = new List<Edge>();
	}

	/// <summary>
	/// 頂点 <paramref name="from"/> から頂点 <paramref name="to"/> への容量 <paramref name="cap"/> の有向辺を追加します．
	/// </summary>
	/// <param name="from">始点となる頂点の 0-indexed での番号</param>
	/// <param name="to">終点となる頂点の 0-indexed での番号</param>
	/// <param name="cap">辺の容量</param>
	/// <remarks>この操作は O(1) で実行されます．</remarks>
	public void AddDirectedEdge(int from, int to, C cap) {
		addEdge(from, to, cap, 0);
	}

	/// <summary>
	/// 頂点 <paramref name="from"/> から頂点 <paramref name="to"/> への容量 <paramref name="cap"/> の無向辺を追加します．
	/// </summary>
	/// <param name="from">始点となる頂点の 0-indexed での番号</param>
	/// <param name="to">終点となる頂点の 0-indexed での番号</param>
	/// <param name="cap">辺の容量</param>
	/// <remarks>この操作は O(1) で実行されます．</remarks>
	public void AddUndirectedEdge(int from, int to, C cap) {
		addEdge(from, to, cap, cap);
	}
	void addEdge(int f, int t, C c1, C c2) {
		var a = new Edge(t, c1);
		var b = new Edge(f, c2);
		Edge.Link(a, b);
		G[f].Add(a);
		G[t].Add(b);
	}
	// 追加
	// ある頂点に張られている辺の一覧を取得。
	// A : from  B : to  C : 容量  D : 流量
	public Tuple<long,long,C,C>[] GetEdges(int from){
		var ret = new List<Tuple<long,long,C,C>>();
		foreach (var e in G[from]) ret.Add(new Tuple<long,long,C,C>(from, e.To, e.Cap+e.Rev.Cap, e.Rev.Cap));
		return ret.ToArray();
	}

	/// <summary>
	/// 頂点 <paramref name="src"/> から頂点 <paramref name="sink"/> へ最大で流量 <paramref name="f"/> だけフローを流します．
	/// </summary>
	/// <param name="src">ソースとなる頂点の 0-indexed での番号</param>
	/// <param name="sink">シンクとなる頂点の 0-indexed での番号</param>
	/// <param name="f">ソースからシンクへと流す最大の容量．-1を指定した場合，最大流を求める．</param>
	/// <remarks>この操作はDinic法に基づき，最悪計算量 O(EV^2) で実行されます．Vは頂点の数，Eは辺の数ｗ表します．</remarks>
	public C Execute(int src, int sink, C f = -1) {
		C flow = 0;
		if (f < 0) f = C.MaxValue;
		while (f > 0)
		{
			bfs(src);
			if (lv[sink] == 0) return flow;
			Array.Clear(iter, 0, iter.Length);
			C df;
			while ((df = dfs(src, sink, f)) > 0) { flow += df; f -= df; }
		}
		return flow;
	}

	void bfs(int s) {
		Array.Clear(lv, 0, lv.Length);
		var q = new Queue<int>();
		lv[s] = 1;
		q.Enqueue(s);
		while (q.Count > 0)
		{
			var v = q.Dequeue();
			foreach (var e in G[v])
				if (e.Cap > 0 && lv[e.To] == 0)
				{
					lv[e.To] = lv[v] + 1;
					q.Enqueue(e.To);
				}
		}

	}
	C dfs(int v, int t, C f) {
		if (v == t) return f;
		C ret = 0;
		for (; iter[v] < G[v].Count; iter[v]++)
		{
			var e = G[v][iter[v]];
			if (e.Cap <= 0 || lv[v] >= lv[e.To]) continue;
			C df = dfs(e.To, t, Math.Min(f, e.Cap));
			if (df <= 0) continue;
			e.Cap -= df;
			e.Rev.Cap += df;
			ret += df; f -= df;
			if (f == 0) break;
		}
		return ret;

	}
	public class Edge {
		public static void Link(Edge e1, Edge e2) {
			e1.Rev = e2; e2.Rev = e1;
		}
		public int To { get; private set; }
		public Edge Rev { get; private set; }
		public C Cap { get; set; }
		public Edge(int t, C c) {
			To = t;
			Cap = c;
		}
		public override string ToString() {
			return string.Format("to: {0}, cap: {1}", To, Cap);
		}
	}
}













}



#region BaseModule


public static class Lib_Minifunc{
	public const long MOD1 = 1000000007; // 10^9+7
	public const double EPS1 = 1e-8;
	public const long INF1 = 1000000000000000;  // 10^15
	[CS.MethodImpl(256)] public static void swap1<T>(ref T a,ref T b) { T t = a; a = b; b = t; }
	[CS.MethodImpl(256)] public static void swap2<T>(ref T a,ref T b) where T : IComparable { if (a.CompareTo(b)==1) swap1(ref a, ref b); }  // b の方が小さければ交換

	[CS.MethodImpl(256)] public static bool chmin<T>(ref T a,T b) where T : IComparable { bool r; if (r = (a.CompareTo(b)== 1)) a = b; return r; }  // b の方が小さければ a を更新
	[CS.MethodImpl(256)] public static bool chmax<T>(ref T a,T b) where T : IComparable { bool r; if (r = (a.CompareTo(b)==-1)) a = b; return r; }  // b の方が大きければ a を更新
	[CS.MethodImpl(256)] public static bool inside(long i,long n) => (0<=i&&i<n);
	[CS.MethodImpl(256)] public static bool inside(long x,long y,long w,long h) => (inside(x,w)&&inside(y,h));
	[CS.MethodImpl(256)] public static T min<T>(params T[] a) where T : IComparable { T m = a[0]; for (int i=1;i<a.Length;i++) chmin(ref m, a[i]); return m; }
	[CS.MethodImpl(256)] public static T max<T>(params T[] a) where T : IComparable { T m = a[0]; for (int i=1;i<a.Length;i++) chmax(ref m, a[i]); return m; }
	[CS.MethodImpl(256)] public static long mod(long a,long m=MOD1) { var v = a%m; return (v<0?(m<0?v-m:v+m):v); }
	[CS.MethodImpl(256)] public static long ceil(long a,long b) => (a%b==0||(a<0&&0<b)||(0<a&&b<0)?a/b:a/b+1);	// 整数商の切り上げ
	[CS.MethodImpl(256)] public static long round(double a) => Convert.ToInt64(a);	// 四捨五入
	public static string YES(bool a) => a?"YES":"NO";
	public static string yes(bool a) => a?"Yes":"No";
	[CS.MethodImpl(256)] public static P<T,U> initp<T,U>(T a,U b) => new P<T,U>(a,b);
	[CS.MethodImpl(256)] public static P<T,U,V> initp<T,U,V>(T a,U b,V c) => new P<T,U,V>(a,b,c);
	[CS.MethodImpl(256)] public static P<T,U,V,W> initp<T,U,V,W>(T a,U b,V c,W d) => new P<T,U,V,W>(a,b,c,d);
	public static T[] initc<T>(long l1) where T : new() { var m = new T[l1]; for (int i=0;i<m.Length;i++) m[i] = new T(); return m; }	// new制約は遅い
	public static int[] range(long s, long c) => Enumerable.Range((int)s,(int)c).ToArray();
	[CS.MethodImpl(256)] public static T[] inita<T>(long l1,T v=default(T)) => Enumerable.Repeat(v,(int)l1).ToArray();
	public static T[][] inita<T>(long l1,long l2,T v=default(T)) { var m = new T[l1][]; for (int i=0;i<m.Length;i++) m[i] = inita(l2,v); return m; }
	public static void shift(this IList<int> l,int o) { for (int i = 0;i<l.Count;i++) l[i]+=o; }
	public static void shift(this IList<long> l,long o) { for (int i = 0;i<l.Count;i++) l[i]+=o; }
	[CS.MethodImpl(256)] public static bool initd<T,U>(this IDictionary<T,U> d, T k, U v=default(U)) { if(d.ContainsKey(k)) { return false; } else { d[k] = v; return true; } }
	public static void sort<T>(this T[] a,int o=1, Comparison<T> f=null) where T : IComparable {
		switch(o){
			case  0: Array.Sort(a,f);break;
			case  1: Array.Sort(a,(x,y)=>x.CompareTo(y));break;
			case -1: Array.Sort(a,(x,y)=>y.CompareTo(x));break;
			default: break;
		}
	}
	public static void sort<T,U>(this P<T,U>[] a,int o, Comparison<P<T,U>> f=null) where T : IComparable where U : IComparable {
		switch(o){
			case  0: Array.Sort(a,f);break;
			case  1: Array.Sort(a,(x,y)=>x.A.CompareTo(y.A));break;
			case -1: Array.Sort(a,(x,y)=>y.A.CompareTo(x.A));break;
			case  2: Array.Sort(a,(x,y)=>x.B.CompareTo(y.B));break;
			case -2: Array.Sort(a,(x,y)=>y.B.CompareTo(x.B));break;
			default: break;
		}
	}
	public static void sort<T,U,V>(this P<T,U,V>[] a,int o, Comparison<P<T,U,V>> f=null) where T : IComparable where U : IComparable where V : IComparable {
		switch(o){
			case  0: Array.Sort(a,f);break;
			case  1: Array.Sort(a,(x,y)=>x.A.CompareTo(y.A));break;
			case -1: Array.Sort(a,(x,y)=>y.A.CompareTo(x.A));break;
			case  2: Array.Sort(a,(x,y)=>x.B.CompareTo(y.B));break;
			case -2: Array.Sort(a,(x,y)=>y.B.CompareTo(x.B));break;
			case  3: Array.Sort(a,(x,y)=>x.C.CompareTo(y.C));break;
			case -3: Array.Sort(a,(x,y)=>y.C.CompareTo(x.C));break;
			default: break;
		}
	}
	public static void sort<T,U,V,W>(this P<T,U,V,W>[] a,int o, Comparison<P<T,U,V,W>> f=null) where T : IComparable where U : IComparable where V : IComparable where W : IComparable {
		switch(o){
			case  0: Array.Sort(a,f);break;
			case  1: Array.Sort(a,(x,y)=>x.A.CompareTo(y.A));break;
			case -1: Array.Sort(a,(x,y)=>y.A.CompareTo(x.A));break;
			case  2: Array.Sort(a,(x,y)=>x.B.CompareTo(y.B));break;
			case -2: Array.Sort(a,(x,y)=>y.B.CompareTo(x.B));break;
			case  3: Array.Sort(a,(x,y)=>x.C.CompareTo(y.C));break;
			case -3: Array.Sort(a,(x,y)=>y.C.CompareTo(x.C));break;
			case  4: Array.Sort(a,(x,y)=>x.D.CompareTo(y.D));break;
			case -4: Array.Sort(a,(x,y)=>y.D.CompareTo(x.D));break;
			default: break;
		}
	}
}


public struct P<T,U>
{
	public T A; public U B;
	public P(T a,U b) { A = a; B = b; }
	public static implicit operator KeyValuePair<T,U>(P<T,U> a) => new KeyValuePair<T,U>(a.A,a.B);
	public static implicit operator P<T,U>(KeyValuePair<T,U> a) => new P<T,U>(a.Key,a.Value);
}
public struct P<T,U,V>
{
	public T A; public U B; public V C;
	public P(T a,U b,V c) { A = a; B = b; C = c; }
}
public struct P<T,U,V,W>
{
	public T A; public U B; public V C; public W D;
	public P(T a,U b,V c,W d) { A = a; B = b; C = c; D = d; }
}

public static class Lib_IO
{
	class Prt : System.IO.StreamWriter
	{
		public override IFormatProvider FormatProvider { get { return System.Globalization.CultureInfo.InvariantCulture; } }
		public Prt(System.IO.Stream s) : base(s,new UTF8Encoding(false,true)) {}
		public Prt(System.IO.Stream s,Encoding e) : base(s,e) {}
	}
	static Prt sw = new Prt(Console.OpenStandardOutput());
	static char[] sp = new char[] {' '};
	[CS.MethodImpl(256)] static bool eq<T,U>() => typeof(T).Equals(typeof(U));
	[CS.MethodImpl(256)] static T ct<T,U>(U a) => (T)Convert.ChangeType(a,typeof(T));
	[CS.MethodImpl(256)] static T cv<T>(string s) =>
		eq<T,int>()	? ct<T,int>(int.Parse(s))
	  : eq<T,long>()   ? ct<T,long>(long.Parse(s))
	  : eq<T,double>() ? ct<T,double>(double.Parse(s,System.Globalization.CultureInfo.InvariantCulture))
	  : eq<T,char>()   ? ct<T,char>(s[0])
					   : ct<T,string>(s);
	public static string[] rm<T>(out T a) {
		var z = Console.ReadLine().Split(sp,StringSplitOptions.RemoveEmptyEntries); 
		a = cv<T>(z[0]);
		return z;
	}
	public static string[] rm<T,U>(out T a,out U b) {
		var z = rm<T>(out a); 
		b = cv<U>(z[1]);
		return z;
	}
	public static string[] rm<T,U,V>(out T a,out U b,out V c) {
		var z = rm<T,U>(out a,out b); 
		c = cv<V>(z[2]);
		return z;
	}
	public static string[] rm<T,U,V,W>(out T a,out U b,out V c,out W d) {
		var z = rm<T,U,V>(out a,out b,out c); 
		d = cv<W>(z[3]);
		return z;
	}
	public static string[] rm<T,U,V,W,X>(out T a,out U b,out V c,out W d,out X e) {
		var z = rm<T,U,V,W>(out a,out b,out c,out d); 
		e = cv<X>(z[4]);
		return z;
	}
	public static string[] rm<T,U,V,W,X,Y>(out T a,out U b,out V c,out W d,out X e,out Y f) {
		var z = rm<T,U,V,W,X>(out a,out b,out c,out d,out e); 
		f = cv<Y>(z[5]);
		return z;
	}
	public static string[] ra<T>(out T[] a) {		
		var z = Console.ReadLine().Split(sp,StringSplitOptions.RemoveEmptyEntries);
		a = new T[z.Length];
		for(int i=0;i<a.Length;i++) a[i] = cv<T>(z[i]);
		return z;
	}
	public static string[][] rl<T>(long n,out T[] a) {
		a = new T[n];
		var y = new string[n][];
		for(int i=0;i<n;i++) y[i] = rm(out a[i]);
		return y;
	}
	public static string[][] rl<T,U>(long n,out P<T,U>[] a) {
		a = new P<T,U>[n];
		var y = new string[n][];
		for(int i=0;i<n;i++) {
			T o; U p;
			y[i] = rm(out o,out p);
			a[i] = new P<T,U>(o,p);
		}
		return y;
	}
	public static string[][] rl<T,U,V>(long n,out P<T,U,V>[] a) {
		a = new P<T,U,V>[n];
		var y = new string[n][];
		for(int i=0;i<n;i++) {
			T o; U p; V q;
			y[i] = rm(out o,out p,out q);
			a[i] = new P<T,U,V>(o,p,q);
		}
		return y;
	}
	public static string[][] rl<T,U,V,W>(long n,out P<T,U,V,W>[] a) {
		a = new P<T,U,V,W>[n];
		var y = new string[n][];
		for(int i=0;i<n;i++) {
			T o; U p; V q; W r;
			y[i] = rm(out o,out p,out q,out r);
			a[i] = new P<T,U,V,W>(o,p,q,r);
		}
		return y;
	}
	public static string[][] rx<T>(long n,out T[][] a) {
		a = new T[n][];
		var y = new string[n][];
		for(int i=0;i<n;i++) y[i] = ra(out a[i]);
		return y;
	}

	static void wwp(Action act){
		sw.AutoFlush = false;
		Console.SetOut(sw);
		act();
		Console.Out.Flush();
		sw.AutoFlush = true;
		Console.SetOut(sw);
	}
	[CS.MethodImpl(256)] static string wfm(Type t) =>t.Equals(typeof(double)) ? "{0:F10}" : "{0}";
	public static void wm(params object[] a) {
		wwp(()=>{
			for(int i=0;i<a.Length-1;i++) Console.Write(wfm(a[i].GetType())+" ",a[i]);
			Console.WriteLine(wfm(a[a.Length-1].GetType()),a[a.Length-1]);
		});
	}
	public static void wa<T>(IList<T> a) { wxa(new IList<T>[]{a}, " "); }
	public static void wl<T>(IList<T> a) {
		wwp(()=>{
			var f = wfm(typeof(T));
			if(a.Count==0){
				Console.WriteLine();
			}else{
				foreach(T x in a) Console.WriteLine(f,x);
			}
		});
	}
	static void wxa<T>(IList<IList<T>> a, string s) {
		wwp(()=>{
			var f = wfm(typeof(T));
			var g = f + s;
			foreach(var b in a) {
				if(b.Count==0){
					Console.WriteLine();
				}else{
					for(int i=0;i<b.Count-1;i++) Console.Write(g,b[i]);
					Console.WriteLine(f,b[b.Count-1]);
				}
			}
		});
	}
	public static void wx<T>(IList<IList<T>> a) { wxa(a, " "); }
	public static void wg<T>(IList<IList<T>> a) { wxa(a, ""); }
}

#endregion



}