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 (Python):
import sys

def input(): return sys.stdin.readline().strip()
def list2d(a, b, c): return [[c] * b for i in range(a)]
def list3d(a, b, c, d): return [[[d] * c for j in range(b)] for i in range(a)]
def list4d(a, b, c, d, e): return [[[[e] * d for j in range(c)] for j in range(b)] for i in range(a)]
def ceil(x, y=1): return int(-(-x // y))
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(N=None): return list(MAP()) if N is None else [INT() for i in range(N)]
def Yes(): print('Yes')
def No(): print('No')
def YES(): print('YES')
def NO(): print('NO')
sys.setrecursionlimit(10**9)
INF = 10**19
MOD = 10**9 + 7
EPS = 10**-10

def build_grid(H, W, intv, _type, space=False, padding=True):
    
    if space:
        _input = lambda: input().split()
    else:
        _input = lambda: input()
    _list = lambda: list(map(_type, _input()))
    
    if padding:
        offset = 1
    else:
        offset = 0
    grid = list2d(H+offset*2, W+offset*2, intv)
    for i in range(offset, H+offset):
        row = _list()
        for j in range(offset, W+offset):
            grid[i][j] = row[j-offset]
    return grid

class Dinic:
    """ 最大流(Dinic)：O(E*V^2) """

    INF = 10**18

    def __init__(self, n):
        self.n = n
        self.links = [[] for _ in range(n)]
        self.depth = None
        self.progress = None
        self.pos = []

    def copy(self):
        res = Dinic(self.n)
        res.links = [[a[:] for a in b] for b in self.links]
        res.pos = [a[:] for a in self.pos]
        return res

    def add_edge(self, _from, to, cap):
        self.pos.append((_from, len(self.links[_from])))
        self.links[_from].append([cap, to, len(self.links[to])])
        self.links[to].append([0, _from, len(self.links[_from]) - 1])

    def bfs(self, s):
        from collections import deque

        depth = [-1] * self.n
        depth[s] = 0
        q = deque([s])
        while q:
            v = q.popleft()
            for cap, to, _ in self.links[v]:
                if cap > 0 and depth[to] < 0:
                    depth[to] = depth[v] + 1
                    q.append(to)
        self.depth = depth

    def dfs(self, v, t, flow):
        if v == t:
            return flow
        links_v = self.links[v]
        for i in range(self.progress[v], len(links_v)):
            self.progress[v] = i
            cap, to, rev = link = links_v[i]
            if cap == 0 or self.depth[v] >= self.depth[to]:
                continue
            d = self.dfs(to, t, min(flow, cap))
            if d == 0:
                continue
            link[0] -= d
            self.links[to][rev][0] += d
            return d
        return 0

    def flow(self, s, t):
        INF = Dinic.INF
        flow = 0
        while True:
            self.bfs(s)
            if self.depth[t] < 0:
                return flow
            self.progress = [0] * self.n
            current_flow = self.dfs(s, t, INF)
            while current_flow > 0:
                flow += current_flow
                current_flow = self.dfs(s, t, INF)

    def get_edge(self, i):
        e = self.links[self.pos[i][0]][self.pos[i][1]]
        re = self.links[e[1]][e[2]]
        
        return (self.pos[i][0], e[1], e[0]+re[0], re[0])

    def get_edges(self):
        M = len(self.pos)
        res = []
        for i in range(M):
            res.append(self.get_edge(i))
        return res

N, M = MAP()
grid = build_grid(N, M, '
N += 2; M += 2

dinic = Dinic(N*M+2)
s = N*M
t = N*M + 1

directions = ((1, 0), (-1, 0), (0, 1), (0, -1))
for i in range(1, N-1):
    for j in range(1, M-1):
        if grid[i][j] == '
            continue
        u = M*i + j
        if (i+j) % 2 == 1:
            dinic.add_edge(s, u, 1)
            for di, dj in directions:
                ni, nj = i+di, j+dj
                v = M*ni + nj
                if grid[ni][nj] == '.':
                    dinic.add_edge(u, v, 1)
        else:
            dinic.add_edge(u, t, 1)

res = dinic.flow(s, t)
edges = dinic.get_edges()
for u, v, cap, f in edges:
    if u not in [s, t] and v not in [s, t] and f:
        ci, cj = divmod(u, M)
        ni, nj = divmod(v, M)
        if ci+1 == ni:
            grid[ci][cj] = 'v'
            grid[ni][nj] = '^'
        elif ci == ni+1:
            grid[ci][cj] = '^'
            grid[ni][nj] = 'v'
        elif cj+1 == nj:
            grid[ci][cj] = '>'
            grid[ni][nj] = '<'
        elif cj == nj+1:
            grid[ci][cj] = '<'
            grid[ni][nj] = '>'

print(res)
for i in range(1, N-1):
    print(''.join(grid[i][1:M-1]))

Solution (Python):
from collections import deque

class mf_graph:
    def __init__(self,N):
        self.N = N
        self.graph = [[] for _ in range(N)]
    
    def add_edge(self,v,w,cap):
        edge = [w,cap,None]
        edge[2] = rev_edge = [v,0,edge]
        self.graph[v].append(edge)
        self.graph[w].append(rev_edge)
    
    def bfs(self,s,t):
        self.level = [None]*self.N
        dq = deque([s])
        self.level[s] = 0
        while dq:
            v = dq.popleft()
            nlevel = self.level[v]+1
            for w,cap,_ in self.graph[v]:
                if cap and self.level[w] is None:
                    self.level[w] = nlevel
                    dq.append(w)
        return self.level[t] is not None
    
    def dfs(self,s,v,f):
        if v == s:
            return f
        for rev in self.it[v]:
            w,_,e = rev
            cap = e[1]
            if cap and self.level[w] is not None:
                if self.level[v] > self.level[w]:
                    d = self.dfs(s,w,min(f,cap))
                    if d:
                        e[1] -= d
                        rev[1] += d
                        return d
        self.level[v] == self.N
        return 0
    
    def flow(self,s,t,flow_limit=float('inf')):
        flow = 0
        while self.bfs(s,t):
            *self.it, = map(iter,self.graph)
            f = flow_limit
            while f:
                f = self.dfs(s,t,flow_limit-flow)
                flow += f
        return flow

N,M = map(int, input().split())
S = [list(input()) for i in range(N)]
dc = mf_graph(N*M+2)

s =N*M
t = N*M+1
for i in range(N):
    for j in range(M):
        if (i+j) % 2 == 0:
            dc.add_edge(s,M*i+j,1)
        else:
            dc.add_edge(M*i+j,t,1)

for i in range(N):
    for j in range(M):
        if j+1 < M and S[i][j] == "." and S[i][j+1] == ".":
            u,v = M*i+j,M*i+j+1
            if (i+j) % 2 == 1:
                u,v = v,u
            dc.add_edge(u,v,1)
        if i+1 < N and S[i][j] == "." and S[i+1][j] == ".":
            u,v = M*i+j, M*(i+1)+j
            if (i+j) % 2 == 1:
                u,v = v,u
            dc.add_edge(u,v,1)

print(dc.flow(s,t,10**9))
for u in range(N*M+2):
    for v,cap,_ in dc.graph[u]:
        ui,uj = divmod(u,M)
        vi,vj = divmod(v,M)
        if (ui+uj) % 2 == 0 and cap == 0 and u != s and u != t and v != s and v!= t:
            if ui+1 == vi:
                S[ui][uj] = "v"
                S[vi][vj] = "^"
            elif ui == vi+1:
                S[ui][uj] = "^"
                S[vi][vj] = "v"
            elif uj+1 == vj:
                S[ui][uj] = ">"
                S[vi][vj] = "<"
            elif uj == vj+1:
                S[ui][uj] = "<"
                S[vi][vj] = ">"

for res in S:
    print("".join(res))

Solution (Python):
from collections import deque

class mf_graph:
    def __init__(self,N):
        self.N = N
        self.graph = [[] for _ in range(N)]
    
    def add_edge(self,v,w,cap):
        edge = [w,cap,None]
        edge[2] = rev_edge = [v,0,edge]
        self.graph[v].append(edge)
        self.graph[w].append(rev_edge)
    
    def bfs(self,s,t):
        self.level = [None]*self.N
        dq = deque([s])
        self.level[s] = 0
        while dq:
            v = dq.popleft()
            nlevel = self.level[v]+1
            for w,cap,_ in self.graph[v]:
                if cap and self.level[w] is None:
                    self.level[w] = nlevel
                    dq.append(w)
        return self.level[t] is not None
    
    def dfs(self,s,v,f):
        if v == s:
            return f
        for rev in self.it[v]:
            w,_,e = rev
            cap = e[1]
            if cap and self.level[w] is not None:
                if self.level[v] > self.level[w]:
                    d = self.dfs(s,w,min(f,cap))
                    if d:
                        e[1] -= d
                        rev[1] += d
                        return d
        self.level[v] == self.N
        return 0
    
    def flow(self,s,t,flow_limit=float('inf')):
        flow = 0
        while self.bfs(s,t):
            *self.it, = map(iter,self.graph)
            f = flow_limit
            while f:
                f = self.dfs(s,t,flow_limit-flow)
                flow += f
        return flow

N,M = map(int, input().split())
S = [list(input()) for i in range(N)]
dc = mf_graph(N*M+2)

s =N*M
t = N*M+1
for i in range(N):
    for j in range(M):
        if (i+j) % 2 == 0:
            dc.add_edge(s,M*i+j,1)
        else:
            dc.add_edge(M*i+j,t,1)

for i in range(N):
    for j in range(M):
        if j+1 < M and S[i][j] == "." and S[i][j+1] == ".":
            u,v = M*i+j,M*i+j+1
            if (i+j) % 2 == 1:
                u,v = v,u
            dc.add_edge(u,v,1)
        if i+1 < N and S[i][j] == "." and S[i+1][j] == ".":
            u,v = M*i+j, M*(i+1)+j
            if (i+j) % 2 == 1:
                u,v = v,u
            dc.add_edge(u,v,1)

print(dc.flow(s,t,10**9))
for u in range(N*M+2):
    for v,cap,_ in dc.graph[u]:
        ui,uj = divmod(u,M)
        vi,vj = divmod(v,M)
        if (ui+uj) % 2 == 0 and cap == 0 and u != s and u != t and v != s and v!= t:
            if ui+1 == vi:
                S[ui][uj] = "v"
                S[vi][vj] = "^"
            elif ui == vi+1:
                S[ui][uj] = "^"
                S[vi][vj] = "v"
            elif uj+1 == vj:
                S[ui][uj] = ">"
                S[vi][vj] = "<"
            elif uj == vj+1:
                S[ui][uj] = "<"
                S[vi][vj] = ">"

for res in S:
    print("".join(res))

Solution (Python):
N,M = map(int,input().split())
S = [input() for i in range(N)]

P = N*M+2
src, dst = N*M, N*M+1
es = [[] for i in range(P)] 
pos = []

def add_edge(fr,to,cap):
    pos.append((fr, len(es[fr])))
    es[fr].append([to,cap,len(es[to])])
    es[to].append([fr,0,len(es[fr])-1])

for i,row in enumerate(S):
    for j,c in enumerate(row):
        if c=='
        if (i+j)%2==0:
            add_edge(src, i*M+j, 1) 
        else:
            add_edge(i*M+j, dst, 1) 

for i,row in enumerate(S):
    for j,c in enumerate(row):
        if c=='
        v = i*M+j
        if i and S[i-1][j]=='.':
            add_edge(v, (i-1)*M+j, 1)
        if j and S[i][j-1]=='.':
            add_edge(v, i*M+j-1, 1)
        if i+1 < N and S[i+1][j]=='.':
            add_edge(v, (i+1)*M+j, 1)
        if j+1 < M and S[i][j+1]=='.':
            add_edge(v, i*M+j+1, 1)

INF = float('inf')
level = [0] * P
iters = [0] * P
from collections import deque
def dinic_max_flow(s,t):
    global iters

    def _bfs(s):
        global level
        level = [-1] * P
        level[s] = 0
        q = deque([s])
        while q:
            v = q.popleft()
            for to,cap,rev in es[v]:
                if cap > 0 and level[to] < 0:
                    level[to] = level[v] + 1
                    q.append(to)

    def _dfs(v,t,f):
        if v == t: return f
        for i in range(iters[v],len(es[v])):
            iters[v] += 1
            to,cap,rev = es[v][i]
            if es[v][i][1] > 0 and level[v] < level[to]:
                d = _dfs(to,t,min(f,es[v][i][1]))
                if d > 0:
                    es[v][i][1] -= d 
                    es[to][rev][1] += d
                    return d
        return 0

    flow = 0
    while True:
        _bfs(s)
        if level[t] < 0: return flow
        iters = [0] * P
        f = 0
        while True:
            f = _dfs(s,t,INF)
            if f <= 0: break
            flow += f

print(dinic_max_flow(src, dst))

ans = [list(row) for row in S]
for fr,i in pos:
    if fr==src: continue
    to,cap,rev = es[fr][i]
    if to==dst: continue
    flow = es[to][rev][1]
    if flow==0: continue
    i0,j0 = divmod(fr,M)
    i1,j1 = divmod(to,M)
    if i0 == i1+1:
        ans[i1][j1] = 'v'
        ans[i0][j0] = '^'
    elif j0 == j1+1:
        ans[i1][j1] = '>'
        ans[i0][j0] = '<'
    elif i0 == i1-1:
        ans[i0][j0] = 'v'
        ans[i1][j1] = '^'
    else:
        ans[i0][j0] = '>'
        ans[i1][j1] = '<'
for row in ans:
    print(''.join(row))

Solution (Python):
class Weigthed_Digraph:
    
    def __init__(self,vertex=[]):
        self.vertex=set(vertex)

        self.edge_number=0
        self.vertex_number=len(vertex)

        self.adjacent_out={v:{} for v in vertex} 
        self.adjacent_in={v:{} for v in vertex} 

    
    def add_vertex(self,*adder):
        for v in adder:
            if v not in self.vertex:
                self.adjacent_in[v]={}
                self.adjacent_out[v]={}

                self.vertex_number+=1
                self.vertex.add(v)

    
    def add_edge(self,From,To,weight=1):
        for v in [From,To]:
            if v not in self.vertex:
                self.add_vertex(v)

        if To not in self.adjacent_in[From]:
            self.edge_number+=1

        self.adjacent_out[From][To]=weight
        self.adjacent_in[To][From]=weight

    
    def remove_edge(self,From,To):
        for v in [From,To]:
            if v not in self.vertex:
                self.add_vertex(v)

        if To in self.adjacent_out[From]:
            del self.adjacent_out[From][To]
            del self.adjacent_in[To][From]
            self.edge_number-=1

    
    def remove_vertex(self,*vertexes):
        for  v in vertexes:
            if v in self.vertex:
                self.vertex_number-=1

                for u in self.adjacent_out[v]:
                    del self.adjacent_in[u][v]
                    self.edge_number-=1
                del self.adjacent_out[v]

                for u in self.adjacent_in[v]:
                    del self.adjacent_out[u][v]
                    self.edge_number-=1
                del self.adjacent_in[v]

    
    def add_walk(self,*walk):
        pass

    
    def add_cycle(self,*cycle):
        pass

    
    def __vertex_swap(self,p,q):
        self.vertex.sort()

    
    def vertex_exist(self,v):
        return v in self.vertex

    
    def edge_exist(self,From,To):
        if not(self.vertex_exist(From) and self.vertex_exist(To)):
            return False
        return To in self.adjacent_out[From]

    
    def neighbohood(self,v):
        if not self.vertex_exist(v):
            return []
        return list(self.adjacent[v])

    
    def out_degree(self,v):
        if not self.vertex_exist(v):
            return 0

        return len(self.adjacent_out[v])

    
    def in_degree(self,v):
        if not self.vertex_exist(v):
            return 0

        return len(self.adjacent_in[v])

    
    def degree(self,v):
        if not self.vertex_exist(v):
            return 0

        return self.out_degree(v)-self.in_degree(v)

    
    def vertex_count(self):
        return len(self.vertex)

    
    def edge_count(self):
        return self.edge_number

    
    def connected_component(self,v):
        pass

def Flow_by_Dinic(D,source,sink,Mode=False):
    from collections import deque
    from copy import copy

    """Source sからSink tへの最大流問題をDinic法で解く.\n

    Mode:
    True---各頂点の流し方も返す
    False---解答のみ
    (参考元:https://tjkendev.github.io/procon-library/python/max_flow/dinic.html)
    """
    def bfs(s,t):
        for v in D.vertex:
            Level[v]=None

        Q=deque([s])
        Level[s]=0

        while Q:
            v=Q.popleft()
            for w,cap,_ in H[v]:
                if cap and Level[w] is None:
                    Level[w]=Level[v]+1
                    Q.append(w)

        return Level[t] is not None

    def dfs(v,t,f):
        if v==t:
            return f

        for e in H[v]:
            w,cap,rev=e
            if cap and Level[v]<Level[w]:
                d=dfs(w,t,min(f,cap))

                if d:
                    e[1]-=d
                    rev[1]+=d
                    return d
        return 0

    s,t=source,sink
    inf=float("inf")
    flow=0
    Level={v:None for v in D.vertex}

    H={v:[] for v in D.vertex}

    for u in D.vertex:
        for v in D.adjacent_out[u]:
            F=[v,D.adjacent_out[u][v],None]
            F[2]=B=[u,0,F]
            H[u].append(F)
            H[v].append(B)

    while bfs(s,t):
        f=inf
        while f:
            f=dfs(s,t,inf)
            flow+=f

    if Mode:
        R={}
        for v in D.vertex:
            R[v]={}
            for S in H[v]:
                w=S[0]
                if w in D.adjacent_out[v]:
                    R[v][w]=S[-1][1]

        return flow,R
    else:
        return flow

N,M=map(int,input().split())
D=Weigthed_Digraph([(y,x) for x in range(1,M+1) for y in range(1,N+1)])
D.add_vertex("s","t")

S=["*"*(M+2) for _ in range(N+2)]
for i in range(1,N+1):
    S[i]="*"+input()+"*"

H=[(1,0),(-1,0),(0,1),(0,-1)]
for y in range(1,N+1):
    for x in range(1,M+1):
        if S[y][x]!=".":
            continue

        if (x+y)%2:
            D.add_edge("s",(y,x),1)
            for (a,b) in H:
                if S[y+a][x+b]==".":
                    D.add_edge((y,x),(y+a,x+b),1)
        else:
            D.add_edge((y,x),"t",1)

flow,F=Flow_by_Dinic(D,"s","t",True)

U=[[S[j][i] for i in range(M+2)] for j in range(N+2)]
for y in range(1,N+1):
    for x in range(1,M+1):
        for C in F[(y,x)]:
            if isinstance(C,str):
                continue
            elif F[(y,x)][C]==0:
                continue

            q,p=C
            if (y+1==q) and (x==p):
                alpha,beta="v","^"
            elif (y-1==q) and (x==p):
                alpha,beta="^","v"
            elif (y==q) and (x+1==p):
                alpha,beta=">","<"
            elif (y==q) and (x-1==p):
                alpha,beta="<",">"

            U[y][x]=alpha
            U[q][p]=beta

print(flow)
Y=["".join(T[1:-1]) for T in U[1:-1]]
print("\n".join(Y))

Solution (Python):
import sys
from collections import *

sys.setrecursionlimit(10 ** 6)
int1 = lambda x: int(x) - 1
p2D = lambda x: print(*x, sep="\n")
def II(): return int(sys.stdin.readline())
def MI(): return map(int, sys.stdin.readline().split())
def MI1(): return map(int1, sys.stdin.readline().split())
def LI(): return list(map(int, sys.stdin.readline().split()))
def LI1(): return list(map(int1, sys.stdin.readline().split()))
def LLI(rows_number): return [LI() for _ in range(rows_number)]
def SI(): return sys.stdin.readline()[:-1]
dij = [(1, 0), (-1, 0), (0, 1), (0, -1)]



class Dinic:
    def __init__(self, n, s, t):
        self.n, self.s, self.t = n, s, t
        self.to = [[] for _ in range(n)]
        self.max_flow = -1

    def add_edge(self, u, v, cap):
        u_index_in_to_v = len(self.to[v])
        v_index_in_to_u = len(self.to[u])
        self.to[u].append([v, cap, u_index_in_to_v])
        self.to[v].append([u, 0, v_index_in_to_u])

    
    def add_undir_edge(self, u, v, cap):
        u_index_in_to_v = len(self.to[v])
        v_index_in_to_u = len(self.to[u])
        self.to[u].append([v, cap, u_index_in_to_v])
        self.to[v].append([u, cap, v_index_in_to_u])

    def __set_level(self):
        s = self.s
        level = [-1] * self.n
        level[s] = 0
        q = deque()
        q.append([s, 0])
        while q:
            u, u_level = q.popleft()
            for v, cap, _ in self.to[u]:
                if cap == 0: continue
                if level[v] != -1: continue
                level[v] = u_level + 1
                if v == self.t:
                    self.level = level
                    return True
                q.append([v, u_level + 1])
        return False

    def __dfs(self, u=-1, flow_to_me=10 ** 16):
        if u == -1: u = self.s
        if u == self.t: return flow_to_me
        flow_from_me = 0
        u_level = self.level[u]
        for utov_i, (v, cap, vtou_i) in enumerate(self.to[u]):
            if self.level[v] != u_level + 1: continue
            if cap == 0: continue
            flow_to_v = self.__dfs(v, min(cap, flow_to_me - flow_from_me))
            if not flow_to_v: continue
            flow_from_me += flow_to_v
            self.to[u][utov_i][1] -= flow_to_v
            self.to[v][vtou_i][1] += flow_to_v
        return flow_from_me

    def __calculation(self):
        res = 0
        while self.__set_level():
            res += self.__dfs()
        return res

    
    def get_max_flow(self):
        if self.max_flow == -1:
            self.max_flow = self.__calculation()
        return self.max_flow

h,w=MI()
ss=[list(SI()) for _ in range(h)]
mf=Dinic(h*w+2,h*w,h*w+1)
for i in range(h):
    for j in range(w):
        if ss[i][j]=="
        if (i+j)%2:
            mf.add_edge(i*w+j,h*w+1,1)
        else:
            mf.add_edge(h*w,i*w+j,1)
            for di,dj in dij:
                ni,nj=i+di,j+dj
                if ni<0 or nj<0 or ni>=h or nj>=w:continue
                if ss[ni][nj]=="
                mf.add_edge(i*w+j,ni*w+nj,1)

ans=mf.get_max_flow()

for i in range(h):
    for j in range(w):
        if (i+j)%2:continue
        u=i*w+j
        for v,cap,_ in mf.to[u]:
            if cap:continue
            if v==h*w:continue
            dir=[w,-w,1,-1].index(u-v)
            ss[i][j]="^v<>"[dir]
            ss[v//w][v%w]="v^><"[dir]

print(ans)
for row in ss:print("".join(row))

Solution (Python):
N,M=map(int,input().split())
S=[list(input()) for i in range(N)]
V=N*M
G=[[] for i in range(V)]
ma=[0]*V
us=[0]*V
def ae(u,v):
  G[u].append(v)
  G[v].append(u)

def df(v):
  us[v]=1
  for i in range(len(G[v])):
    u=G[v][i]
    w=ma[u]
    if w<0 or(not(us[w]) and df(w)):
      ma[v]=u
      ma[u]=v
      return 1
  return 0

def mat():
  r=0
  for i in range(V):
    ma[i]=-1
  for v in range(V):
    if ma[v]<0:
      for i in range(V):
        us[i]=0
      if df(v):
        r+=1
  return r

w4y=[1,0,-1,0]
w4x=[0,1,0,-1]
for i in range(N):
  for j in range(M):
    if ((i+j+1)&1)and(S[i][j]=='.'):
      for k in range(4):
        k=[i+w4y[k],j+w4x[k]]
        if min(k)<0 or k[0]>=N or k[1]>=M:
          continue
        if S[k[0]][k[1]]=='.':
          ae(i*M+j,k[0]*M+k[1])
print(mat())
for i in range(N):
  for j in range(M):
    if ma[i*M+j]<0:
      continue
    if ma[i*M+j]==i*M+j+M:
      S[i][j]='v'
    elif ma[i*M+j]==i*M+j-M:
      S[i][j]='^'
    elif ma[i*M+j]==i*M+j+1:
      S[i][j]='>'
    elif ma[i*M+j]==i*M+j-1:
      S[i][j]='<'
  print(''.join(S[i]))

Solution (Python):

from collections import deque
from typing import List

Edge = List[int]  


class Dinic:
    """Dinic class to solve max-find_max_flow / min-cut problems.
    References:
        https://ikatakos.com/pot/programming_algorithm/graph_theory/maximum_flow
        http://vartkw.hatenablog.com/entry/2016/12/02/002703
    """

    __slots__ = ["_size", "graph", "_depth", "_progress"]

    def __init__(self, size: int) -> None:
        self._size = size
        self.graph: List[List[Edge]] = [[] for _ in range(size)]
        self._depth = [-1] * size
        self._progress = [0] * size

    def add(self, from_: int, to: int, cap: int = 1, is_directed: bool = True) -> None:
        """Add an edge."""
        self.graph[from_].append([to, cap, len(self.graph[to])])
        self.graph[to].append([from_, 0, len(self.graph[from_]) - 1])
        if not is_directed:
            self.add(to, from_, cap)

    def find_max_flow(self, source: int, target: int, inf: int = 1 << 30) -> int:
        """Find the max-find_max_flow from source to target in O(N^{2}M)."""
        flow = 0
        while True:
            self._bfs(source)
            if self._depth[target] < 0:
                break
            self._progress = [0] * self._size
            cur_flow = self._dfs(source, target, inf)
            while cur_flow:
                flow += cur_flow
                cur_flow = self._dfs(source, target, inf)
        return flow

    def _bfs(self, source: int) -> None:
        depth = [-1] * self._size
        depth[source] = 0
        queue = deque([source])
        while queue:
            v = queue.popleft()
            for to, cap, _ in self.graph[v]:
                if cap > 0 > depth[to]:
                    depth[to] = depth[v] + 1
                    queue.append(to)
        self._depth = depth

    def _dfs(self, v: int, target: int, flow: int) -> int:
        if v == target:
            return flow
        v_edges = self.graph[v]
        for i in range(self._progress[v], len(v_edges)):
            self._progress[v] = i
            to, cap, rev = v_edges[i]
            if not cap or self._depth[v] >= self._depth[to]:
                continue
            d = self._dfs(to, target, min(flow, cap))
            if not d:
                continue
            v_edges[i][1] -= d
            self.graph[to][rev][1] += d
            return d
        return 0


def practice2_d():
    
    N, M = map(int, input().split())
    S = [list(input()) for _ in range(N)]
    dc = Dinic(N * M + 2)

    s = N * M
    t = N * M + 1
    for i in range(N):
        for j in range(M):
            if (i + j) % 2 == 0:
                dc.add(s, M * i + j)
            else:
                dc.add(M * i + j, t)

    for i in range(N):
        for j in range(M):
            if j + 1 < M and S[i][j] == "." and S[i][j + 1] == ".":
                u, v = M * i + j, M * i + j + 1
                if (i + j) % 2:
                    u, v = v, u
                dc.add(u, v)
            if i + 1 < N and S[i][j] == "." and S[i + 1][j] == ".":
                u, v = M * i + j, M * (i + 1) + j
                if (i + j) % 2:
                    u, v = v, u
                dc.add(u, v)

    print(dc.find_max_flow(s, t))
    for u in range(N * M + 2):
        for v, cap, _ in dc.graph[u]:
            ui, uj = divmod(u, M)
            vi, vj = divmod(v, M)
            if (
                not (ui + uj) % 2
                and not cap
                and u != s
                and u != t
                and v != s
                and v != t
            ):
                if ui + 1 == vi:
                    S[ui][uj] = "v"
                    S[vi][vj] = "^"
                elif ui == vi + 1:
                    S[ui][uj] = "^"
                    S[vi][vj] = "v"
                elif uj + 1 == vj:
                    S[ui][uj] = ">"
                    S[vi][vj] = "<"
                elif uj == vj + 1:
                    S[ui][uj] = "<"
                    S[vi][vj] = ">"

    for res in S:
        print("".join(res))


if __name__ == "__main__":
    practice2_d()