Imagine a city with n horizontal streets crossing m vertical streets, forming an (n - 1) × (m - 1) grid. In order to increase the traffic flow, mayor of the city has decided to make each street one way. This means in each horizontal street, the traffic moves only from west to east or only from east to west. Also, traffic moves only from north to south or only from south to north in each vertical street. It is possible to enter a horizontal street from a vertical street, or vice versa, at their intersection.

 [Image] 

The mayor has received some street direction patterns. Your task is to check whether it is possible to reach any junction from any other junction in the proposed street direction pattern.


-----Input-----

The first line of input contains two integers n and m, (2 ≤ n, m ≤ 20), denoting the number of horizontal streets and the number of vertical streets.

The second line contains a string of length n, made of characters '<' and '>', denoting direction of each horizontal street. If the i-th character is equal to '<', the street is directed from east to west otherwise, the street is directed from west to east. Streets are listed in order from north to south.

The third line contains a string of length m, made of characters '^' and 'v', denoting direction of each vertical street. If the i-th character is equal to '^', the street is directed from south to north, otherwise the street is directed from north to south. Streets are listed in order from west to east.


-----Output-----

If the given pattern meets the mayor's criteria, print a single line containing "YES", otherwise print a single line containing "NO".


-----Examples-----
Input
3 3
><>
v^v

Output
NO

Input
4 6
<><>
v^v^v^

Output
YES



-----Note-----

The figure above shows street directions in the second sample test case.

Difficulty: MEDIUM

Solutions:
from sys import stdin, stdout
(N, M) = map(int, stdin.readline().strip().split())
req = [[[-1, -1] for __ in range(M)] for __ in range(N)]
input1 = stdin.readline().strip()
input2 = stdin.readline().strip()
for i in range(N):
	curx = 1 if input1[i] == '>' else -1
	for j in range(M):
		cury = -1 if input2[j] == '^' else 1
		req[i][j] = [cury, curx]
condn = True
for i in range(N):
	for j in range(M):
		notVisited = [[True for __ in range(M)] for __ in range(N)]
		count = N * M - 1
		stack = [(i, j)]
		notVisited[i][j] = False
		while stack:
			(curX, curY) = stack.pop()
			(modX, modY) = (curX + req[curX][curY][0], curY + req[curX][curY][1])
			if modX >= 0 and modX < N and notVisited[modX][curY]:
				stack.append((modX, curY))
				notVisited[modX][curY] = False
				count -= 1
			if modY >= 0 and modY < M and notVisited[curX][modY]:
				stack.append((curX, modY))
				notVisited[curX][modY] = False
				count -= 1
		if count:
			condn = False
			break
	if not condn:
		break
if condn:
	stdout.write('YES')
else:
	stdout.write('NO')


(n, m) = map(int, input().split())
a = input()
b = input()
if a[0] == '>' and a[n - 1] == '<' and (b[0] == '^') and (b[m - 1] == 'v'):
	print('YES')
elif a[n - 1] == '>' and a[0] == '<' and (b[m - 1] == '^') and (b[0] == 'v'):
	print('YES')
else:
	print('NO')


import os
import sys
from io import BytesIO, IOBase

def main():
	(n, m) = map(int, input().split())
	h = list(input())
	v = list(input())
	graph = [set() for _ in range(n * m)]
	zz = 0
	for i in range(n):
		if h[i] == '>':
			for j in range(i * m, i * m + m - 1):
				graph[j].add(j + 1)
				zz = j + 1
		else:
			for j in range(i * m + 1, i * m + m):
				graph[j].add(j - 1)
				zz = j - 1
	for i in range(m):
		if v[i] == 'v':
			for j in range(i, i + n * m - m, m):
				graph[j].add(j + m)
				zz = j + m
		else:
			for j in range(i + m, n * m, m):
				graph[j].add(j - m)
				zz = j - m
	stack = [zz]
	vis = [0] * (n * m)
	while stack:
		z = stack.pop()
		if vis[z]:
			continue
		vis[z] = 1
		for item in graph[z]:
			if vis[item] == 0:
				stack.append(item)
	for i in range(n * m):
		if vis[i] == 0:
			print('NO')
			exit()
	print('YES')
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


(n, m) = map(int, input().split())
rows = input()
columns = input()

def DFS(rows, columns, n, m):
	ans = set()
	for i in range(1, n + 1):
		for j in range(1, m + 1):
			stack = [(i, j)]
			visited = set()
			while len(stack):
				(tempx, tempy) = stack.pop()
				visited.add((tempx, tempy))
				if (tempx, tempy) in ans:
					ans.add((i, j))
					break
				if tempx < n and columns[tempy - 1] == '^' and ((tempx + 1, tempy) not in visited):
					stack.append((tempx + 1, tempy))
				elif tempx - 1 >= 1 and columns[tempy - 1] == 'v' and ((tempx - 1, tempy) not in visited):
					stack.append((tempx - 1, tempy))
				if tempy < m and rows[tempx - 1] == '<' and ((tempx, tempy + 1) not in visited):
					stack.append((tempx, tempy + 1))
				elif tempy - 1 >= 1 and rows[tempx - 1] == '>' and ((tempx, tempy - 1) not in visited):
					stack.append((tempx, tempy - 1))
			if len(visited) == n * m:
				ans.add((i, j))
	if len(ans) == n * m:
		print('YES')
	else:
		print('NO')
DFS(rows, columns, n, m)


Read = lambda : map(int, input().split())
while True:
	try:
		input()
	except:
		break
	x = input()
	y = input()
	u = x[0] + x[-1] + y[0] + y[-1] not in ('><^v', '<>v^')
	print('YNEOS'[u::2])


import sys
mod = 1000000007

def get_array():
	return list(map(int, sys.stdin.readline().split()))

def get_ints():
	return map(int, sys.stdin.readline().split())

def input():
	return sys.stdin.readline()

def print_array(a):
	print(' '.join(map(str, a)))

def connected(graph, x):
	visited = [False] * len(graph)
	visited[x] = True
	q = []
	q.append(graph[x])
	while q:
		temp = q.pop(0)
		for e in temp:
			if not visited[e]:
				visited[e] = True
				q.append(graph[e])
	return False if False in visited else True

def main():
	(n, m) = get_ints()
	h = input()
	v = input()
	graph = [[] for _ in range(n * m)]
	intersections = [[m * i + x for x in range(m)] for i in range(n)]
	for i in range(n):
		if h[i] == '>':
			for j in range(1, m):
				graph[intersections[i][j - 1]].append(intersections[i][j])
		else:
			for j in range(1, m):
				graph[intersections[i][j]].append(intersections[i][j - 1])
	for i in range(m):
		if v[i] == 'v':
			for j in range(1, n):
				graph[intersections[j - 1][i]].append(intersections[j][i])
		else:
			for j in range(1, n):
				graph[intersections[j][i]].append(intersections[j - 1][i])
	flag = True
	for i in range(0, n * m):
		flag = flag & connected(graph, i)
		if not flag:
			break
	print('YES' if flag else 'NO')
main()


import sys
inf = float('inf')
mod = 1000000007

def get_array():
	return list(map(int, sys.stdin.readline().split()))

def get_ints():
	return map(int, sys.stdin.readline().split())

def input():
	return sys.stdin.readline()
graph = [[] for _ in range(405)]
graph_reverse = [[] for _ in range(405)]
visited = [False] * 405
visited_other = [False] * 405
stack = []
scc = 0

def explore(node):
	visited[node] = True
	for neighbour in graph_reverse[node]:
		if visited[neighbour] == False:
			explore(neighbour)
	stack.append(node)

def dfs(n, m):
	for i in range(n):
		for j in range(1, m + 1):
			if visited[i * m + j] == False:
				explore(i * m + j)

def explore_other(node):
	visited_other[node] = True
	for neighbour in graph[node]:
		if visited_other[neighbour] == False:
			explore_other(neighbour)

def dfs_o(n, m):
	global scc
	for node in reversed(stack):
		if visited_other[node] == False:
			scc += 1
			explore_other(node)

def main():
	(n, m) = get_ints()
	horizontal = input().strip()
	for i in range(n):
		if horizontal[i] == '<':
			for j in range(1, m):
				graph[i * m + j + 1].append(i * m + j)
				graph_reverse[i * m + j].append(i * m + j + 1)
		else:
			for j in range(1, m):
				graph[i * m + j].append(i * m + (j + 1))
				graph_reverse[i * m + (j + 1)].append(i * m + j)
	vertical = input().strip()
	for j in range(1, m + 1):
		if vertical[j - 1] == '^':
			for i in range(n - 1):
				graph[(i + 1) * m + j].append(i * m + j)
				graph_reverse[i * m + j].append((i + 1) * m + j)
		else:
			for i in range(n - 1):
				graph[i * m + j].append((i + 1) * m + j)
				graph_reverse[(i + 1) * m + j].append(i * m + j)
	dfs(n, m)
	dfs_o(n, m)
	print('YES' if scc == 1 else 'NO')
main()


(n, m) = list(map(int, input().split()))
h = input()
v = input()
if '<' in h and '>' in h and ('v' in v) and ('^' in v):
	if h[0] == '<' and v[0] == '^' or (h[-1] == '>' and v[-1] == 'v') or (h[0] == '>' and v[-1] == '^') or (h[-1] == '<' and v[0] == 'v'):
		print('NO')
	else:
		print('YES')
else:
	print('NO')


from sys import stdin
__author__ = 'artyom'
stdin.readline()
p = stdin.readline().strip()
q = stdin.readline().strip()
print('YES' if p[0] == '>' and p[-1] == '<' and (q[0] == '^') and (q[-1] == 'v') or (p[0] == '<' and p[-1] == '>' and (q[0] == 'v') and (q[-1] == '^')) else 'NO')


(n, m) = list(map(int, input().split()))
arr = list(input())
arr2 = list(input())
k = f'{arr[0]}{arr2[-1]}{arr[-1]}{arr2[0]}'
if k == '>v<^' or k == '<^>v':
	print('YES')
else:
	print('NO')


(n, m) = map(int, input().split())
s = input()
s1 = input()
if s[0] == '>' and s[-1] == '<' and (s1[0] == '^') and (s1[-1] == 'v') or (s[0] == '<' and s[-1] == '>' and (s1[0] == 'v') and (s1[-1] == '^')):
	print('YES')
else:
	print('NO')


input()
s1 = input()
s2 = input()
s3 = s1[0] + s1[-1] + s2[0] + s2[-1]
print((s3 == '<>v^' or s3 == '><^v') and 'YES' or 'NO')


import collections

def bfs(graph, start):
	visited = set()
	q = collections.deque()
	q.append(start)
	while q:
		curr = q.pop()
		if curr not in visited:
			visited.add(curr)
			q.extend(graph[curr])
	return len(visited)

def add_neighbors(graph, start, end, direc):
	for i in range(start, end, direc):
		graph[i].append(i + direc)
(rows, cols) = map(int, input().split())
graph = {}
for r in range(rows):
	for c in range(cols):
		graph[cols * r + c] = []
row_dir = input()
for i in range(rows):
	if row_dir[i] == '>':
		add_neighbors(graph, i * cols, i * cols + cols - 1, 1)
	else:
		add_neighbors(graph, i * cols + cols - 1, i * cols, -1)
col_dir = input()
for i in range(cols):
	if col_dir[i] == 'v':
		add_neighbors(graph, i, i + (rows - 1) * cols, cols)
	else:
		add_neighbors(graph, i + (rows - 1) * cols, i, -cols)
reach_all = True
for r in range(rows):
	for c in range(cols):
		if rows * cols != bfs(graph, r * cols + c):
			reach_all = False
if reach_all:
	print('YES')
else:
	print('NO')


input()
horiz = input()
vert = input()
m = horiz[0] + horiz[-1] + vert[0] + vert[-1]
print('YES' if m in ('><^v', '<>v^') else 'NO')


(n, m) = map(int, input().split())
sn = input()
sm = input()
cir = sn[0] + sm[0] + sn[-1] + sm[-1]
if cir == '<v>^' or cir == '>^<v':
	print('YES')
else:
	print('NO')


import sys
(n, m) = (int(x) for x in sys.stdin.readline().split())
hdir = [-1 if c == '<' else 1 for c in sys.stdin.readline()[:-1]]
vdir = [-1 if c == '^' else 1 for c in sys.stdin.readline()[:-1]]
goal = n * m
for i in range(m):
	for j in range(n):
		visited = set()
		queue = [(i, j)]
		while len(queue) != 0:
			start = queue.pop()
			if start in visited:
				continue
			visited.add(start)
			x = start[0]
			y = start[1]
			newX = x + hdir[y]
			newY = y + vdir[x]
			if newX >= 0 and newX < m:
				queue.append((newX, y))
			if newY >= 0 and newY < n:
				queue.append((x, newY))
		if len(visited) != goal:
			print('NO')
			sys.exit(0)
print('YES')


import copy
hor_ver = list(map(int, input().split(' ')))
hor = hor_ver[0]
ver = hor_ver[1]
hor_dirs = []
ver_dirs = []
hor_dirs.append(0)
ver_dirs.append(0)
hors = input()
for c in hors:
	if c == '<':
		hor_dirs.append(0)
	else:
		hor_dirs.append(1)
vers = input()
for c in vers:
	if c == '^':
		ver_dirs.append(0)
	else:
		ver_dirs.append(1)
nodes = {}
visited_list = {}
for w in range(1, hor_ver[0] + 1):
	for h in range(1, hor_ver[1] + 1):
		nodes[w, h] = [hor_dirs[w], ver_dirs[h]]
		visited_list[w, h] = False

def printm(iter_visit):
	count = 0
	elems = [(x, y) for x in range(1, 5) for y in range(1, 7)]
	for e in elems:
		if count % 6 == 0:
			print('')
		print(1 if iter_visit[e] else 0, end='\t')
		count += 1

def traverse(node):
	directions = nodes[node]
	q = []
	q.append(node)
	iter_visit = copy.deepcopy(visited_list)
	iter_visit[node] = True
	visited = 1
	while len(q) > 0:
		temp = q.pop(0)
		directions = nodes[temp]
		if directions[0] == 1:
			if temp[1] < ver and iter_visit[temp[0], temp[1] + 1] == False:
				new = (temp[0], temp[1] + 1)
				iter_visit[new] = True
				visited += 1
				q.append(new)
		elif not temp[1] == 1 and iter_visit[temp[0], temp[1] - 1] == False:
			new = (temp[0], temp[1] - 1)
			iter_visit[new] = True
			visited += 1
			q.append(new)
		if directions[1] == 1:
			if temp[0] < hor and iter_visit[temp[0] + 1, temp[1]] == False:
				new = (temp[0] + 1, temp[1])
				iter_visit[new] = True
				visited += 1
				q.append(new)
		elif not temp[0] == 1 and iter_visit[temp[0] - 1, temp[1]] == False:
			new = (temp[0] - 1, temp[1])
			iter_visit[new] = True
			visited += 1
			q.append(new)
	return visited
win = True
for node in nodes:
	totalNodes = hor_ver[0] * hor_ver[1]
	visited = traverse(node)
	if not visited == totalNodes:
		win = False
		break
if win:
	print('YES')
else:
	print('NO')


input()
line1 = list(input())
line2 = list(input())
char1 = line1[0]
char2 = line1[-1]
char3 = line2[0]
char4 = line2[-1]
if char1 == '<' and char2 == '>' and (char3 == 'v') and (char4 == '^'):
	print('YES')
elif char1 == '>' and char2 == '<' and (char3 == '^') and (char4 == 'v'):
	print('YES')
else:
	print('NO')


from collections import deque

def gather_input():
	(n, m) = [int(x) for x in input().split()]
	hor_streets = list(input())
	vert_streets = list(input())
	return (hor_streets, vert_streets)

def gen_graph(hor_streets, vert_streets):
	graph = {}
	for i in range(len(hor_streets)):
		for j in range(len(vert_streets)):
			node_str = str(j) + str(i)
			if node_str not in graph:
				graph[node_str] = []
			if vert_streets[j] == '^' and i > 0:
				graph[node_str].append(str(j) + str(i - 1))
			elif vert_streets[j] == 'v' and i < len(hor_streets) - 1:
				graph[node_str].append(str(j) + str(i + 1))
			if hor_streets[i] == '<' and j > 0:
				graph[node_str].append(str(j - 1) + str(i))
			elif hor_streets[i] == '>' and j < len(vert_streets) - 1:
				graph[node_str].append(str(j + 1) + str(i))
	return graph

def dfs(graph, source):
	visited = set()
	stack = deque()
	stack.append(source)
	while len(stack) > 0:
		node_str = stack.pop()
		visited.add(node_str)
		adj_list = graph[node_str]
		for node in adj_list:
			if node not in visited:
				stack.append(node)
	return len(graph) == len(visited)
(hor_streets, vert_streets) = gather_input()
graph = gen_graph(hor_streets, vert_streets)
valid = True
for (source, val) in graph.items():
	if not dfs(graph, source):
		valid = False
		break
if valid:
	print('YES')
else:
	print('NO')


(n, m) = map(int, input().split())
ns = input()
ms = input()
if ns[0] == '<' and ns[n - 1] == '>' and (ms[0] == 'v') and (ms[m - 1] == '^'):
	print('YES')
elif ns[0] == '>' and ms[m - 1] == 'v' and (ns[n - 1] == '<') and (ms[0] == '^'):
	print('YES')
else:
	print('NO')


data = input().split()
n = int(data[0])
m = int(data[1])
h = input().rstrip()
v = input().rstrip()
f = h[0] == '<' and v[0] == 'v' and (v[-1] == '^') and (h[-1] == '>') or (h[0] == '>' and v[0] == '^' and (v[-1] == 'v') and (h[-1] == '<'))
print('YES' if f else 'NO')


(h, w) = map(int, input().split())
go = [[[] for x in range(w)] for y in range(h)]
s = input()
for i in range(h):
	if s[i] == '>':
		for j in range(w - 1):
			go[i][j].append((i, j + 1))
	else:
		for j in range(1, w):
			go[i][j].append((i, j - 1))
s = input()
for i in range(w):
	if s[i] == '^':
		for j in range(1, h):
			go[j][i].append((j - 1, i))
	else:
		for j in range(h - 1):
			go[j][i].append((j + 1, i))
good = True
for i in range(h):
	for j in range(w):
		u = [[False for x in range(w)] for y in range(h)]
		u[i][j] = True
		q = [(i, j)]
		hd = 0
		while hd < len(q):
			for g in go[q[hd][0]][q[hd][1]]:
				if not u[g[0]][g[1]]:
					u[g[0]][g[1]] = True
					q.append(g)
			hd += 1
		if len(q) != h * w:
			good = False
print('YES' if good else 'NO')


(n, m) = map(int, input().split())
a = input()
b = input()
t = a[0] + b[0] + a[-1] + b[-1]
if t == '<v>^' or t == '>^<v':
	print('YES')
else:
	print('NO')


calles = input().split(' ')
hori = int(calles[0])
vert = int(calles[1])
dir_hori = input()
dir_vert = input()
nodos = hori * vert
L_ady = {}
for i in range(hori):
	if dir_hori[i] == '>':
		for j in range(vert):
			L_ady[i, j] = []
			if j != vert - 1:
				L_ady[i, j].append((i, j + 1))
			if i != 0 and dir_vert[j] == '^':
				L_ady[i, j].append((i - 1, j))
			elif i != hori - 1 and dir_vert[j] == 'v':
				L_ady[i, j].append((i + 1, j))
	else:
		for j in range(vert):
			L_ady[i, j] = []
			if j != 0:
				L_ady[i, j].append((i, j - 1))
			if i != 0 and dir_vert[j] == '^':
				L_ady[i, j].append((i - 1, j))
			elif i != hori - 1 and dir_vert[j] == 'v':
				L_ady[i, j].append((i + 1, j))

def recorrer(nodo, l):
	l.append(nodo)
	for conexion in L_ady[nodo]:
		if conexion not in l:
			recorrer(conexion, l)
	if len(l) == len(L_ady):
		return True

def ejecutar():
	for mi_nodo in L_ady:
		l = []
		a = recorrer(mi_nodo, l)
		if a == None:
			print('NO')
			return
	print('YES')
ejecutar()


import sys
sys.setrecursionlimit(20000)

def dfs(s, adj, visited):
	(a, b) = s
	if visited[a][b]:
		return
	visited[a][b] = 1
	for s2 in adj[s]:
		dfs(s2, adj, visited)

def main():
	(n, m) = map(int, input().split())
	adj = {}
	for i in range(n):
		for j in range(m):
			adj[i, j] = []
	(s1, s2) = (input(), input())
	for i in range(n):
		for j in range(m):
			if s1[i] == '<':
				if j > 0:
					adj[i, j].append((i, j - 1))
			elif j + 1 < m:
				adj[i, j].append((i, j + 1))
	for j in range(m):
		for i in range(n):
			if s2[j] == '^':
				if i > 0:
					adj[i, j].append((i - 1, j))
			elif i + 1 < n:
				adj[i, j].append((i + 1, j))
	visited = [[0 for i in range(m)] for j in range(n)]
	check = [[1 for i in range(m)] for j in range(n)]
	ans = True
	for i in range(n):
		for j in range(m):
			visited = [[0 for i in range(m)] for j in range(n)]
			dfs((i, j), adj, visited)
			ans &= visited == check
	print('YES' if ans else 'NO')
main()


from functools import reduce
from operator import *
from math import *
from sys import *
from string import *
setrecursionlimit(10 ** 7)
dX = [0, 0, 1, -1, 1, -1, 1, -1]
dY = [1, -1, 0, 0, 1, -1, -1, 1]
RI = lambda : list(map(int, input().split()))
RS = lambda : input().rstrip().split()
RI()
x = RS()[0]
y = RS()[0]
a = ''.join(x[0] + x[-1] + y[0] + y[-1])
print('YES' if a == '<>v^' or a == '><^v' else 'NO')


(n, m) = [int(i) for i in input().split()]
lr = input()
ud = input()

class inter:

	def __init__(self):
		self.outs = []
city = [inter() for i in range(len(lr) * len(ud))]
inv_city = [inter() for i in range(len(lr) * len(ud))]
for i in range(len(lr)):
	for j in range(len(ud)):
		if lr[i] == '>':
			if j != len(ud) - 1:
				city[i * len(ud) + j].outs.append(i * len(ud) + j + 1)
				inv_city[i * len(ud) + j + 1].outs.append(i * len(ud) + j)
		if lr[i] == '<':
			if j != 0:
				city[i * len(ud) + j].outs.append(i * len(ud) + j - 1)
				inv_city[i * len(ud) + j - 1].outs.append(i * len(ud) + j)
		if ud[j] == '^':
			if i != 0:
				city[i * len(ud) + j].outs.append((i - 1) * len(ud) + j)
				inv_city[(i - 1) * len(ud) + j].outs.append(i * len(ud) + j)
		if ud[j] == 'v':
			if i != len(lr) - 1:
				city[i * len(ud) + j].outs.append((i + 1) * len(ud) + j)
				inv_city[(i + 1) * len(ud) + j].outs.append(i * len(ud) + j)

def dfs(n):
	vis.add(n)
	for i in city[n].outs:
		if i not in vis:
			dfs(i)

def inv_dfs(n):
	inv_vis.add(n)
	for i in inv_city[n].outs:
		if i not in inv_vis:
			inv_dfs(i)
vis = set()
inv_vis = set()
dfs(0)
inv_dfs(0)
if len(vis) == len(inv_vis) and len(vis) == n * m:
	print('YES')
else:
	print('NO')


(n, m) = [int(x) for x in input().split()]
h = input()
v = input()
con = h[0] + v[0] + h[n - 1] + v[m - 1]
if con == '<v>^' or con == '>^<v':
	print('YES')
else:
	print('NO')


(n, m) = map(int, input().split())
s1 = input()
s2 = input()
s3 = ''
s3 += s1[0] + s2[-1] + s1[-1] + s2[0]
print('YES' if s3 == '<^>v' or s3 == '>v<^' else 'NO')


def magic(arr, h1, h2, v1, v2):
	if h1 == '>':
		arr[1] += 1
	else:
		arr[0] += 1
	if h2 == '>':
		arr[3] += 1
	else:
		arr[2] += 1
	if v1 == '^':
		arr[0] += 1
	else:
		arr[2] += 1
	if v2 == '^':
		arr[1] += 1
	else:
		arr[3] += 1
(n, m) = [int(x) for x in input().split()]
h = input()
v = input()
corners = [0, 0, 0, 0]
magic(corners, h[0], h[n - 1], v[0], v[m - 1])
print('YES') if all(corners) else print('NO')


import sys

def solve(r, w):
	data = r.readline().split()
	east_west = list(r.readline())
	east_west.pop()
	north_south = list(r.readline())
	north_south.pop()
	if east_west[0] == '<' and east_west[-1] == '>' and (north_south[0] == 'v') and (north_south[-1] == '^') or (east_west[0] == '>' and east_west[-1] == '<' and (north_south[0] == '^') and (north_south[-1] == 'v')):
		print('YES')
	else:
		print('NO')
solve(sys.stdin, sys.stdout)


from collections import deque
dic = {'>': (0, 1), '<': (0, -1), 'v': (1, 0), '^': (-1, 0)}
([n, m], hor, vert) = (map(int, input().split()), input().strip(), input().strip())
for _x in range(n):
	for _y in range(m):
		(q, d) = (deque([(_x, _y)]), [[0] * m for x in range(n)])
		d[_x][_y] = 1
		while q:
			(x, y) = q.popleft()
			for direction in '><v^':
				(dx, dy) = dic[direction]
				if -1 < x + dx < n and -1 < y + dy < m and (vert[y] == direction if dx else hor[x] == direction) and (not d[x + dx][y + dy]):
					d[x + dx][y + dy] = 1
					q.append((x + dx, y + dy))
		if sum(sum(d, [])) != n * m:
			print('NO')
			break
	else:
		continue
	break
else:
	print('YES')


from collections import Counter
(n, m) = map(int, input().split())

def build_graph():
	GI = Counter()
	GO = Counter()
	l = input().strip()
	for (i, s) in enumerate(l):
		if s == '>':
			for j in range(m - 1):
				GO[i * m + j] += 1
				GI[i * m + j + 1] += 1
		else:
			for j in range(1, m):
				GO[i * m + j] += 1
				GI[i * m + j - 1] += 1
	l = input().strip()
	for (j, s) in enumerate(l):
		if s == 'v':
			for i in range(n - 1):
				GO[i * m + j] += 1
				GI[(i + 1) * m + j] += 1
		else:
			for i in range(1, n):
				GO[i * m + j] += 1
				GI[(i - 1) * m + j] += 1
	return (GI, GO)
(GI, GO) = build_graph()
for (v, c) in GI.items():
	if c == 0 or GO[v] == 0:
		print('NO')
		exit(0)
print('YES')


(n, m) = [int(x) for x in input().split()]
a = input()
b = input()
if a[0] == '<' and b[0] == 'v' and (a[-1] == '>') and (b[-1] == '^'):
	print('YES')
elif a[0] == '>' and b[-1] == 'v' and (a[-1] == '<') and (b[0] == '^'):
	print('YES')
else:
	print('NO')


from _collections import defaultdict

def DFexplo(dictAdj, start):
	explored = {start}
	lifo = [start]
	while len(lifo) > 0:
		node = lifo.pop()
		for child in dictAdj[node]:
			if child not in explored:
				explored.add(child)
				lifo.append(child)
	return explored

def solve(dictAdj):
	for i in range(len(H)):
		for j in range(len(V)):
			nodesReachable = DFexplo(dictAdj, (i, j))
			if len(nodesReachable) < n * m - 1:
				return False
	return True

def isNode(i, j):
	return 0 <= i < n and 0 <= j < m

def buildGraph(H, V):
	dictAdj = defaultdict(list)
	for i in range(len(H)):
		for j in range(len(V)):
			if isNode(i, j - 1) and H[i] == '<':
				dictAdj[i, j].append((i, j - 1))
			if isNode(i, j + 1) and H[i] == '>':
				dictAdj[i, j].append((i, j + 1))
			if isNode(i - 1, j) and V[j] == '^':
				dictAdj[i, j].append((i - 1, j))
			if isNode(i + 1, j) and V[j] == 'v':
				dictAdj[i, j].append((i + 1, j))
	return dictAdj
(n, m) = map(int, input().split())
H = input()
V = input()
dictAdj = buildGraph(H, V)
if solve(dictAdj):
	print('YES')
else:
	print('NO')


from sys import stdin
(n, m) = [int(x) for x in stdin.readline().rstrip().split()]
h = stdin.readline().rstrip()
v = stdin.readline().rstrip()
con = h[0] + v[0] + h[n - 1] + v[m - 1]
if con == '<v>^' or con == '>^<v':
	print('YES')
else:
	print('NO')


def dfs(start, graph_d, visited_d):
	if not visited_d[start]:
		visited_d[start] = True
		for u in graph_d[start]:
			dfs(u, graph_d, visited_d)
	return visited_d
(n, m) = map(int, input().split())
s_n = input()
s_m = input()
graph = [[] for i in range(n * m)]
for i in range(n):
	for j in range(m):
		if s_n[i] == '>' and j < m - 1:
			graph[i * m + j].append(i * m + j + 1)
		elif s_n[i] == '<' and j > 0:
			graph[i * m + j].append(i * m + j - 1)
		if s_m[j] == '^' and i > 0:
			graph[i * m + j].append((i - 1) * m + j)
		elif s_m[j] == 'v' and i < n - 1:
			graph[i * m + j].append((i + 1) * m + j)
is_perf = True
for i in range(n * m):
	visited = [False] * (n * m)
	res = dfs(i, graph, visited)
	for elem in res:
		if not elem:
			is_perf = False
			break
if is_perf:
	print('YES')
else:
	print('NO')


input()
s1 = input()
s2 = input()
c = s1[0] + s1[len(s1) - 1] + s2[0] + s2[len(s2) - 1]
if c == '<>v^' or c == '><^v':
	print('YES')
else:
	print('NO')


(n, m) = map(int, input().split())
horizontal = input()
vertical = input()
visited = [[0 for j in range(m)] for i in range(n)]

def isSafe(x, y):
	if x >= 0 and y >= 0 and (x < n) and (y < m):
		return True
	return False

def explore(i, j):
	visited[i][j] = 1
	if isSafe(i + 1, j) and vertical[j] == 'v' and (visited[i + 1][j] == 0):
		explore(i + 1, j)
	if isSafe(i - 1, j) and vertical[j] == '^' and (visited[i - 1][j] == 0):
		explore(i - 1, j)
	if isSafe(i, j + 1) and horizontal[i] == '>' and (visited[i][j + 1] == 0):
		explore(i, j + 1)
	if isSafe(i, j - 1) and horizontal[i] == '<' and (visited[i][j - 1] == 0):
		explore(i, j - 1)
explore(0, 0)
t1 = 0
for i in range(n):
	for j in range(m):
		if visited[i][j] == 0:
			t1 += 1
visited = [[0 for j in range(m)] for i in range(n)]
explore(n - 1, m - 1)
t2 = 0
for i in range(n):
	for j in range(m):
		if visited[i][j] == 0:
			t2 += 1
if t1 > 0 or t2 > 0:
	print('NO')
else:
	print('YES')


input()
horiz = input()
vert = input()
num_horiz = len(horiz)
num_vert = len(vert)
num_junc = num_horiz * num_vert
grid = [[0 for j in range(num_junc)] for i in range(num_junc)]
for i in range(num_horiz):
	for j in range(num_vert):
		p = i * num_vert + j
		if horiz[i] == '>' and j + 1 < num_vert:
			grid[p][p + 1] = 1
		elif horiz[i] == '<' and j - 1 >= 0:
			grid[p][p - 1] = 1
		if vert[j] == 'v' and i + 1 < num_horiz:
			grid[p][p + num_vert] = 1
		elif vert[j] == '^' and i - 1 >= 0:
			grid[p][p - num_vert] = 1
cached_visits = [[] for x in range(num_junc)]
good_city = True
for (idx, adj_nodes) in enumerate(grid):
	visited = [0 for x in range(num_junc)]
	visited[idx] = 1
	s = [adj_idx for (adj_idx, val) in enumerate(adj_nodes) if val]
	while s:
		node_idx = s.pop()
		visited[node_idx] = 1
		for already_visited in cached_visits[node_idx]:
			visited[already_visited] = 1
		new_possible_nodes = [idx for (idx, val) in enumerate(grid[node_idx]) if val and (not visited[idx])]
		s += new_possible_nodes
	cached_visits[idx] = [visited_idx for (visited_idx, val) in enumerate(visited) if val]
	if visited.count(0):
		good_city = False
		break
print('YES' if good_city else 'NO')


(n, m) = map(int, input('').split())
row_order = [char for char in input('')]
col_order = [char for char in input('')]

class Node:

	def __init__(self, id):
		(self.row_id, self.col_id) = id
		self.children = []

	def add_child(self, child_node_id):
		self.children.append(child_node_id)

def add_horizontal_edge(row_dir, row_id, col_id):
	if row_dir == '>' and col_id < m - 1:
		matrix[row_id][col_id].add_child((row_id, col_id + 1))
	elif row_dir == '<' and col_id > 0:
		matrix[row_id][col_id].add_child((row_id, col_id - 1))

def add_vertical_edge(col_dir, row_id, col_id):
	if col_dir == '^' and row_id > 0:
		matrix[row_id][col_id].add_child((row_id - 1, col_id))
	elif col_dir == 'v' and row_id < n - 1:
		matrix[row_id][col_id].add_child((row_id + 1, col_id))
matrix = [[Node((row_id, col_id)) for col_id in range(m)] for row_id in range(n)]
for row_id in range(n):
	row_dir = row_order[row_id]
	for col_id in range(m):
		col_dir = col_order[col_id]
		add_horizontal_edge(row_dir, row_id, col_id)
		add_vertical_edge(col_dir, row_id, col_id)

def explore(row_id, col_id, visited):
	if visited[row_id][col_id] == 'true':
		return
	else:
		visited[row_id][col_id] = 'true'
		for (child_row_id, child_col_id) in matrix[row_id][col_id].children:
			explore(child_row_id, child_col_id, visited)
	return
answer = 'YES'

def dfs(answer):
	for row_id in range(n):
		for col_id in range(m):
			visited = [['false' for col_id in range(m)] for row_id in range(n)]
			explore(row_id, col_id, visited)
			for i in range(n):
				for j in range(m):
					if visited[i][j] == 'false':
						answer = 'NO'
						return answer
	return answer
answer = dfs(answer)
print(answer)


from math import inf

def cin():
	return map(int, input().split(' '))
(n, m) = cin()
p = n * m
h = list(input())
v = list(input())
mayor = {i: [] for i in range(p)}
mayordash = {i: [] for i in range(p)}
for i in range(n):
	for j in range(m - 1):
		temp = i * m
		if h[i] == '>':
			mayordash[temp + j + 1].append(temp + j)
			mayor[temp + j].append(temp + j + 1)
		else:
			mayordash[temp + j].append(temp + j + 1)
			mayor[temp + j + 1].append(temp + j)
for i in range(m):
	for j in range(n - 1):
		temp = i + j * m
		if v[i] != '^':
			mayor[temp].append(temp + m)
			mayordash[temp + m].append(temp)
		else:
			mayor[temp + m].append(temp)
			mayordash[temp].append(temp + m)
visited = [False for i in range(p)]
cnt = 0

def dfs(graph, idx):
	global visited
	global cnt
	cnt += 1
	for v in graph[idx]:
		if visited[v] == False:
			visited[v] = True
			dfs(graph, v)
visited[0] = True
dfs(mayor, 0)
ans = cnt
cnt = 0
visited = [False for i in range(p)]
visited[0] = True
dfs(mayordash, 0)
print('YES') if cnt == ans and cnt == p else print('NO')


def bfs(a, b, i, j, n, m):
	queue = [[i, j]]
	mark = {i: {j: False for j in range(m)} for i in range(n)}
	(n, m) = (n - 1, m - 1)
	res = 0
	while queue:
		q = queue.pop(0)
		(x, y) = (q[0], q[1])
		if mark[x][y] == True:
			continue
		mark[x][y] = True
		res += 1
		if a[x] == '<':
			if y > 0:
				if mark[x][y - 1] == False:
					queue.append([x, y - 1])
		elif y < m:
			if mark[x][y + 1] == False:
				queue.append([x, y + 1])
		if b[y] == '^':
			if x > 0:
				if mark[x - 1][y] == False:
					queue.append([x - 1, y])
		elif x < n:
			if mark[x + 1][y] == False:
				queue.append([x + 1, y])
	return res
(n, m) = map(int, input().split())
a = {i: x for (i, x) in enumerate(input())}
b = {i: x for (i, x) in enumerate(input())}
oh = n * m
for i in range(n):
	for j in range(m):
		res = bfs(a, b, i, j, n, m)
		if res != oh:
			print('NO')
			from sys import exit
			exit()
print('YES')


(n, m) = map(int, input().split())
s1 = input()
s2 = input()
s = s1[0] + s2[0] + s1[n - 1] + s2[m - 1]
print('YES' if s in ['<v>^', '>^<v'] else 'NO')


def main():
	(n, m) = map(int, input().split())
	a = input()
	b = input()
	valid = a[0] == '>' and a[-1] == '<' and (b[0] == '^') and (b[-1] == 'v') or (a[0] == '<' and a[-1] == '>' and (b[0] == 'v') and (b[-1] == '^'))
	print('YES' if valid else 'NO')
main()


MOD = 1000000007
ii = lambda : int(input())
si = lambda : input()
dgl = lambda : list(map(int, input()))
f = lambda : map(int, input().split())
il = lambda : list(map(int, input().split()))
ls = lambda : list(input())
(n, m) = f()
bf = si()
ud = si()
x = bf[0] + ud[-1] + bf[-1] + ud[0]
if x in ['>v<^', '<^>v']:
	print('YES')
else:
	print('NO')


from collections import deque
(n, m) = map(int, input().split())
hor = [1 if char == '>' else -1 for char in input()]
vert = [1 if char == 'v' else -1 for char in input()]

def solve(n, m, hor, vert):
	for r in range(n):
		for c in range(m):
			if not explore(n, m, hor, vert, (r, c)):
				return False
	return True

def explore(n, m, hor, vert, start_pos):
	visited = [[0] * m for _ in range(n)]
	count = 0
	nodes = deque([start_pos])
	visited[start_pos[0]][start_pos[1]] = 1
	while nodes:
		(r, c) = nodes.popleft()
		count += 1
		(r_inc, c_inc) = (vert[c], hor[r])
		for (dr, dc) in [(r + r_inc, c), (r, c + c_inc)]:
			if 0 <= dr < n and 0 <= dc < m and (not visited[dr][dc]):
				nodes.append((dr, dc))
				visited[dr][dc] = 1
	return count == n * m
if solve(n, m, hor, vert):
	print('YES')
else:
	print('NO')


import math
import sys
from collections import defaultdict
from collections import Counter
from collections import deque
import bisect
sys.setrecursionlimit(1000000)
input = iter(sys.stdin.buffer.read().decode().splitlines()).__next__
ilele = lambda : map(int, input().split())
alele = lambda : list(map(int, input().split()))
G = defaultdict(list)

def addEdge(a, b):
	G[a].append(b)

def DFSutil(node, vis):
	vis[node] = True
	for child in G.get(node, []):
		if vis.get(child, True) == False:
			DFSutil(child, vis)

def dfs(points):
	vis = {}
	for i in range(n):
		for j in range(m):
			vis[i, j] = False
	DFSutil((0, 0), vis)
	return all(vis.values())
(n, m) = ilele()
S1 = input()
S2 = input()
if n == m == 1:
	print('YES')
elif S1[0] == '<' and S2[0] == '^' or (S1[0] == '>' and S2[-1] == '^') or (S1[-1] == '<' and S2[0] == 'v') or (S1[-1] == '>' and S2[-1] == 'v'):
	print('NO')
else:
	for i in range(n):
		for j in range(m):
			if i == 0:
				if S1[i] == '>':
					if j != m - 1:
						addEdge((i, j), (i, j + 1))
				elif j != 0:
					addEdge((i, j), (i, j - 1))
				if S2[j] == 'v':
					if i != n - 1:
						addEdge((i, j), (i + 1, j))
			elif i == n - 1:
				if S1[i] == '>':
					if j != m - 1:
						addEdge((i, j), (i, j + 1))
				elif j != 0:
					addEdge((i, j), (i, j - 1))
				if S2[j] == '^':
					if i != 0:
						addEdge((i, j), (i - 1, j))
			else:
				if S1[i] == '>':
					if j != m - 1:
						addEdge((i, j), (i, j + 1))
				elif j != 0:
					addEdge((i, j), (i, j - 1))
				if S2[j] == '^':
					if i != 0:
						addEdge((i, j), (i - 1, j))
				elif i != n - 1:
					addEdge((i, j), (i + 1, j))
	points = n * m
	if dfs(points):
		print('YES')
	else:
		print('NO')


from copy import copy
import re
import inspect
from sys import argv, exit

def rstr():
	return input()

def rint():
	return int(input())

def rints(splitchar=' '):
	return [int(i) for i in input().split(splitchar)]

def varnames(obj, namespace=globals()):
	return [name for name in namespace if namespace[name] is obj]

def pvar(var, override=False):
	prnt(varnames(var), var)

def prnt(*args, override=False):
	if '-v' in argv or override:
		print(*args)

def done(covered):
	for r in covered:
		for c in r:
			if not c:
				return False
	return True

def check(r, c, covered):
	if r < 0 or c < 0 or r >= len(covered[0]) or (c >= len(covered)):
		return False
	if done(covered):
		return True
	if rdirs[r] == 'l':
		if cdirs[c] == 'u':
			return check(r - 1, c, copy(covered)) or check(r, c - 1, copy(covered))
		else:
			return check(r - 1, c, copy(covered)) or check(r, c + 1, copy(covered))
	elif cdirs[c] == 'u':
		return check(r + 1, c, copy(covered)) or check(r, c - 1, copy(covered))
	else:
		return check(r + 1, c, copy(covered)) or check(r, c + 1, copy(covered))

def bettercheck(rdirs, cdirs):
	if rdirs[0] == 'l' and cdirs[0] == 'd' and (rdirs[-1] == 'r') and (cdirs[-1] == 'u'):
		print('YES')
		exit(0)
	if rdirs[0] == 'r' and cdirs[0] == 'u' and (rdirs[-1] == 'l') and (cdirs[-1] == 'd'):
		print('YES')
		exit(0)
	print('NO')
(r, c) = rints()
rdirs = ['l' if r == '<' else 'r' for r in rstr()]
cdirs = ['u' if r == '^' else 'd' for r in rstr()]
bettercheck(rdirs, cdirs)


(n, m) = map(int, input().split(' '))
h = [1 if i == '>' else -1 for i in list(input())]
v = [1 if i == 'v' else -1 for i in list(input())]
connected = True
for a in range(n):
	for b in range(m):
		vi = [[0 for i in range(m)] for j in range(n)]
		s = [(a, b)]
		while len(s) > 0:
			(x, y) = s.pop()
			if vi[x][y] == 1:
				continue
			vi[x][y] = 1
			i = x + v[y]
			if 0 <= i < n:
				s.append((i, y))
			j = y + h[x]
			if 0 <= j < m:
				s.append((x, j))
		for i in range(n):
			for j in range(m):
				if vi[i][j] == 0:
					connected = False
		if not connected:
			break
	if not connected:
		break
print('YES' if connected else 'NO')


(u, v) = map(int, input().split())
s1 = input()
s2 = input()
result = s1[0] + s2[-1] + s1[-1] + s2[0]
print('YES' if result in ('>v<^', '<^>v') else 'NO')


def dfs(node):
	global seen
	stack = [node]
	while stack:
		ele = stack.pop(-1)
		if seen[ele] == 0:
			seen[ele] = 1
			for each in arr[ele]:
				if seen[each] == 0:
					stack.append(each)
(n, m) = map(int, input().split())
arr = [list() for i in range(n * m)]
hor = input()
ver = input()
h = 0
for x in range(0, n * m, m):
	v = 0
	for i in range(x, x + m):
		if hor[h] == '>' and v != m - 1:
			arr[i].append(i + 1)
		elif i != x and hor[h] == '<':
			arr[i].append(i - 1)
		if ver[v] == 'v' and h != n - 1:
			arr[i].append(i + m)
		elif h != 0 and ver[v] == '^':
			arr[i].append(i - m)
		v += 1
	h += 1
for i in range(n * m):
	seen = [0] * (n * m)
	dfs(i)
	if not all(seen):
		print('NO')
		break
else:
	print('YES')


(n, m) = map(int, input().split())
a = input()
b = input()
f = True

def dfs(x, y):
	tmp = 1
	used[x + y * 42] = 1
	if a[x] == '>' and y + 1 < m:
		if used[x + (y + 1) * 42] == 0:
			tmp += dfs(x, y + 1)
	if a[x] == '<' and y - 1 >= 0:
		if used[x + (y - 1) * 42] == 0:
			tmp += dfs(x, y - 1)
	if b[y] == 'v' and x + 1 < n:
		if used[x + 1 + y * 42] == 0:
			tmp += dfs(x + 1, y)
	if b[y] == '^' and x - 1 >= 0:
		if used[x - 1 + y * 42] == 0:
			tmp += dfs(x - 1, y)
	return tmp
for i in range(n):
	for j in range(m):
		used = [0] * 1000
		if dfs(i, j) != n * m:
			f = False
if f:
	print('YES')
else:
	print('NO')


import sys
mod = 1000000007

def get_array():
	return list(map(int, sys.stdin.readline().split()))

def get_ints():
	return map(int, sys.stdin.readline().split())

def input():
	return sys.stdin.readline()

def print_array(a):
	print(' '.join(map(str, a)))

def main():
	(n, m) = get_ints()
	h = input()
	v = input()
	s = h[0] + h[n - 1] + v[0] + v[m - 1]
	print('YES' if s == '<>v^' or s == '><^v' else 'NO')
main()


def dfs(x, y):
	if not graph[2][x + graph[0][x][y]][y]:
		graph[2][x + graph[0][x][y]][y] = True
		dfs(x + graph[0][x][y], y)
	if not graph[2][x][y + graph[1][x][y]]:
		graph[2][x][y + graph[1][x][y]] = True
		dfs(x, y + graph[1][x][y])
(n, m) = list(map(int, input().split()))
c = chr(0)
flag1 = True
graph = [[[0] * (n + 1) for i in range(m + 1)], [[0] * (n + 1) for i in range(m + 1)], [[False] * (n + 1) for i in range(m + 1)]]
s = input()
for i in range(n):
	c = s[i]
	if c == '<':
		for j in range(1, m):
			graph[0][j][i] = -1
	else:
		for j in range(m - 1):
			graph[0][j][i] = 1
s = input()
for i in range(m):
	c = s[i]
	if c == '^':
		for j in range(1, n):
			graph[1][i][j] = -1
	else:
		for j in range(n - 1):
			graph[1][i][j] = 1
for i in range(n):
	for j in range(m):
		flag = False
		if flag1:
			for k in range(n):
				for l in range(m):
					graph[2][l][k] = False
			graph[2][j][i] = True
			dfs(j, i)
			for k in range(n):
				for l in range(m):
					if graph[2][l][k] == False:
						flag = True
			if flag:
				print('NO')
				flag1 = not flag
if flag1:
	print('YES')


(n, m) = map(int, input().split())
horizontal = str(input())
visited = []
h = []
vertical = str(input())
v = []
for char in horizontal:
	if char == '>':
		h.append(int(1))
	else:
		h.append(int(-1))
for char in vertical:
	if char == 'v':
		v.append(int(1))
	else:
		v.append(int(-1))

def travel(ni, mi):
	leftright = h[ni]
	updown = v[mi]
	visited.append([ni, mi])
	newn = ni + updown
	newm = mi + leftright
	if newn >= 0 and newn < n and ([newn, mi] not in visited):
		travel(newn, mi)
	if newm >= 0 and newm < m and ([ni, newm] not in visited):
		travel(ni, newm)
	return visited

def solve():
	lst = [[0, 0], [0, m - 1], [n - 1, 0], [n - 1, m - 1]]
	visited = []
	for l in lst:
		visited.clear()
		vis = travel(l[0], l[1])
		if len(vis) != m * n:
			print('NO')
			return
		visited.clear()
		vis.clear()
	print('YES')
solve()


(n, m) = map(int, input().split())
x = input()
y = input()
(a, b, c, d) = (x[0], x[-1], y[0], y[-1])
if a == '>' and b == '<' and (c == '^') and (d == 'v'):
	print('YES')
elif a == '<' and b == '>' and (c == 'v') and (d == '^'):
	print('YES')
else:
	print('NO')


(n, m) = map(int, input().split())
h = input()
v = input()

def compliments(V, H):
	if H is '>' and V is 'v' or (H is '<' and V is '^'):
		return True
	else:
		return False
if h[0] is not h[len(h) - 1] and v[0] is not v[len(v) - 1] and compliments(v[0], h[len(h) - 1]) and compliments(v[len(v) - 1], h[0]):
	print('YES')
else:
	print('NO')


(m, n) = map(int, input().split())
c = input()
r = input()
if c[0] == '>' and c[-1] == '<' and (r[0] == '^') and (r[-1] == 'v') or (c[0] == '<' and c[-1] == '>' and (r[0] == 'v') and (r[-1] == '^')):
	print('YES')
else:
	print('NO')


import heapq
from copy import deepcopy
import random

class Graph:

	def __init__(self, nodes):
		self.num = nodes
		self._nodes = list((Node(x) for x in range(self.num + 1)))
		self._edges = dict()

	def add_edge(self, start, end, weight=1):
		self._nodes[start].add_edge(self._nodes[end], weight)
		if (start, end) in self._edges:
			d = self._edges[start, end]
			if d['weight'] < weight:
				d['weight'] = weight
		else:
			self._edges[start, end] = {'weight': weight}

	def get_edge_data(self, u, v):
		return self._edges[u, v]

	def unmark_all(self):
		for node in self._nodes:
			node.unmark()

	def get_all_edges(self):
		return deepcopy(self._edges)

	def get_ad_count(self, vert):
		return self._nodes[vert].adj_c

	def nodes(self):
		return list((node.id for node in self._nodes))

	def neighbors(self, vert):
		return list((node.id for node in self._nodes[vert].adjacent))

	def dijkstra(self, start):
		q = []
		q.append(self._nodes[start])
		self._nodes[start].weight = 0
		heapq.heapify(q)
		while len(q):
			current = heapq.heappop(q)
			if current.visit:
				continue
			current.mark()
			for (adj, edge_weight) in current.adjacent.items():
				if not adj.visit:
					if adj.weight > current.weight + edge_weight:
						adj.weight = current.weight + edge_weight
						adj.prev = current
					heapq.heappush(q, adj)
		self.unmark_all()
		d = dict()
		for i in range(1, len(self._nodes)):
			d[i] = self._nodes[i].weight
		return d

	def pathfromHere(self, current):
		path = [current]
		while current.prev:
			path.append(current.prev)
			current = current.prev
		return reversed(path)

	def strongConn(self):
		self.unmark_all()
		toVisit = [self._nodes[1]]
		while len(toVisit):
			current = toVisit.pop()
			if current.visit:
				continue
			current.mark()
			for adj in current.adjacent:
				if not adj.visit:
					toVisit.append(adj)
		for n in range(len(self._nodes)):
			if n == 0:
				continue
			elif self._nodes[n].visit == False:
				return False
		return True

class Node:

	def __init__(self, x):
		self.id = x
		self.visit = False
		self.adjacent = {}
		self.weight = float('inf')
		self.prev = None
		self.adj_c = 0

	def add_edge(self, other, weight):
		if other not in self.adjacent:
			self.adjacent[other] = weight
			self.adj_c += 1
		elif self.adjacent[other] > weight:
			self.adjacent[other] = weight

	def __lt__(self, other):
		return self.weight < other.weight

	def __gt__(self, other):
		return self.weight > other.weight

	def __le__(self, other):
		return self.weight <= other.weight

	def __ge__(self, other):
		return self.weight >= other.weight

	def __ne__(self, other):
		return self.weight != other.weight

	def __hash__(self):
		return self.id

	def mark(self):
		self.visit = True

	def unmark(self):
		self.visit = False

	def __str__(self):
		return str(self.id)
details = input().split()
n = int(details[0])
m = int(details[1])
g1 = Graph(m * n)
g2 = Graph(m * n)
horizontal = input()
vertical = input()
base = 1
for h in range(n):
	if horizontal[h] == '<':
		for v in range(m - 1):
			g1.add_edge(base + v + 1, base + v)
			g2.add_edge(base + v, base + v + 1)
	elif horizontal[h] == '>':
		for v in range(m - 1):
			g2.add_edge(base + v + 1, base + v)
			g1.add_edge(base + v, base + v + 1)
	base += m
base = 1
for h in range(n - 1):
	for v in range(m):
		if vertical[v] == 'v':
			g1.add_edge(base + v, base + v + m)
			g2.add_edge(base + v + m, base + v)
		elif vertical[v] == '^':
			g2.add_edge(base + v, base + v + m)
			g1.add_edge(base + v + m, base + v)
	base += m
if g1.strongConn() and g2.strongConn():
	print('YES')
else:
	print('NO')


from collections import deque
(n, m) = list(map(int, input().split()))
s1 = input()
s2 = input()
ok = True
for i in range(n):
	for j in range(m):
		c = [[False for _ in range(m)] for __ in range(n)]
		c[i][j] = True
		q = deque()
		q.append((i, j))
		while len(q) > 0:
			(x, y) = q.popleft()
			if s1[x] == '>' and y + 1 < m and (not c[x][y + 1]):
				c[x][y + 1] = True
				q.append((x, y + 1))
			elif s1[x] == '<' and y - 1 >= 0 and (not c[x][y - 1]):
				c[x][y - 1] = True
				q.append((x, y - 1))
			if s2[y] == '^' and x - 1 >= 0 and (not c[x - 1][y]):
				c[x - 1][y] = True
				q.append((x - 1, y))
			elif s2[y] == 'v' and x + 1 < n and (not c[x + 1][y]):
				c[x + 1][y] = True
				q.append((x + 1, y))
		for a in range(n):
			for b in range(m):
				if not c[a][b]:
					ok = False
if ok:
	print('YES')
else:
	print('NO')


import sys, os, io
import math, bisect, operator
(inf, mod) = (float('inf'), 10 ** 9 + 7)
from itertools import groupby, accumulate
from heapq import heapify, heappop, heappush
from collections import deque, Counter, defaultdict
I = lambda : int(sys.stdin.buffer.readline())
Neo = lambda : list(map(int, sys.stdin.buffer.readline().split()))
(n, m) = Neo()
s = input()
t = input()
if t[0] + s[-1] + t[-1] + s[0] in ['v>^<'] or t[0] + s[0] + t[-1] + s[-1] in ['^>v<']:
	print('YES')
else:
	print('NO')


import sys
from math import sqrt, gcd, ceil, log
from collections import defaultdict, Counter, deque
input = sys.stdin.readline
read = lambda : list(map(int, input().strip().split()))

def main():
	(n, m) = read()
	s = input().strip()
	t = input().strip()
	ans = s[0] + s[-1] + t[0] + t[-1]
	if ans in ('<>v^', '><^v'):
		print('YES')
	else:
		print('NO')
main()


def AddEdges(direction, i, m, graph):
	if direction == '>':
		for j in range(m - 1):
			graph[i + 1, j + 1].append((i + 1, j + 2))
	else:
		for j in range(m - 1, 0, -1):
			graph[i + 1, j + 1].append((i + 1, j))

def AddEdgesVer(direction, i, n, graph):
	if direction == '^':
		for j in range(n - 1, 0, -1):
			graph[j + 1, i + 1].append((j, i + 1))
	else:
		for j in range(n - 1):
			graph[j + 1, i + 1].append((j + 2, i + 1))

def IsConnected(graph, curr):
	isVisited = {}
	for i in graph:
		isVisited[i] = False
	cmpnts = []
	stack = [curr]
	while stack:
		curr = stack.pop()
		if not isVisited[curr]:
			isVisited[curr] = True
			cmpnts.append(curr)
			for kid in graph[curr]:
				stack.append(kid)
	if len(cmpnts) == len(graph.keys()):
		return True
	return False

def Solve(graph):
	count = 0
	for i in graph:
		if IsConnected(graph, i):
			count += 1
	if count == len(graph):
		print('YES')
		return
	print('NO')

def main():
	graph = {}
	(n, m) = map(int, input().split())
	for i in range(n):
		for j in range(m):
			graph[i + 1, j + 1] = []
	horizontal = input()
	vertical = input()
	for i in range(n):
		direction = horizontal[i]
		AddEdges(direction, i, m, graph)
	for i in range(m):
		direction = vertical[i]
		AddEdgesVer(direction, i, n, graph)
	Solve(graph)
main()


import math, sys, bisect, heapq
from collections import defaultdict, Counter, deque
from itertools import groupby, accumulate
int1 = lambda x: int(x) - 1
input = iter(sys.stdin.buffer.read().decode().splitlines()).__next__
ilele = lambda : map(int, input().split())
alele = lambda : list(map(int, input().split()))
ilelec = lambda : map(int1, input().split())
alelec = lambda : list(map(int1, input().split()))

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 Y(c):
	print(['NO', 'YES'][c])

def y(c):
	print(['no', 'yes'][c])

def Yy(c):
	print(['No', 'Yes'][c])
(n, m) = ilele()
s1 = input()
s2 = input()
Y(s1[0] == '<' and s1[-1] == '>' and (s2[0] == 'v') and (s2[-1] == '^') or (s1[0] == '>' and s1[-1] == '<' and (s2[0] == '^') and (s2[-1] == 'v')))


import sys

class Node:

	def __init__(self, id):
		self.id = id
		self.adjacent = set()
		self.visited = 0

	def addEdge(self, edge):
		self.adjacent.add(edge)

class Graph:

	def __init__(self, numNodes, startNode):
		self.nodes = list()
		self.startNode = startNode
		self.result = 0
		self.dfslist = list()
		for num in range(1, numNodes + 1):
			tempNode = Node(num)
			self.nodes.append(tempNode)

	def dfs(self, node):
		if node.visited:
			return
		node.visited = True
		self.dfslist.append(node.id)
		for n in node.adjacent:
			self.dfs(g.findNode(n))

	def numConnectedComponents(self):
		s = set()
		result = 0
		for n in self.nodes:
			oldsize = len(s)
			self.addAllAdjacentVertices(n, s)
			if len(s) is not oldsize:
				result += 1
		return result

	def addAllAdjacentVertices(self, node, set):
		set.add(node.id)
		self.findNode(node.id).visited = 1
		for edge in node.adjacent:
			if self.findNode(edge).visited is not 1:
				self.addAllAdjacentVertices(self.findNode(edge), set)

	def numNodesReachable(self, node):
		return self.nodesHelper(node, 0)

	def nodesHelper(self, currNode, numSteps):
		self.result += 1
		currNode.visited = 1
		for edge in currNode.adjacent:
			if self.findNode(edge).visited is not 1:
				self.nodesHelper(self.findNode(edge), numSteps + 1)
		return self.result

	def clearVisited(self):
		for node in self.nodes:
			node.visited = 0
		self.result = 0
		self.dfslist.clear()

	def findNode(self, id):
		for node in self.nodes:
			if id == node.id:
				return node

	def findPath(self):
		stack = list()
		answer = list()
		stack.append(self.findNode(self.startNode))
		while len(stack) != 0:
			v = stack[len(stack) - 1]
			if len(v.adjacent) == 0:
				answer.append(v.id)
				stack.pop()
			else:
				edge = v.adjacent.pop()
				self.findNode(edge).adjacent.remove(v.id)
				stack.append(self.findNode(edge))
		return answer
line = sys.stdin.readline().rstrip()
temp = line.split(' ')
numRows = int(temp[0])
numCols = int(temp[1])
g = Graph(numRows * numCols, 1)
line2 = sys.stdin.readline().rstrip()
line3 = sys.stdin.readline().rstrip()
rl = list(line2)
ud = list(line3)
for row in range(0, numRows):
	for col in range(0, numCols):
		nodeNumber = row * numCols + col + 1
		node = g.findNode(nodeNumber)
		if rl[row] == '>':
			if col + 1 < numCols:
				dest = row * numCols + col + 2
				node.addEdge(dest)
		elif col - 1 >= 0:
			dest = row * numCols + col
			node.addEdge(dest)
		if ud[col] == '^':
			if row - 1 >= 0:
				dest = (row - 1) * numCols + col + 1
				node.addEdge(dest)
		elif row + 1 < numRows:
			dest = (row + 1) * numCols + col + 1
			node.addEdge(dest)
weGood = True
g.dfs(g.findNode(1))
for n in range(1, numRows * numCols + 1):
	if n not in g.dfslist:
		weGood = False
		break
if not weGood:
	print('NO')
else:
	g.clearVisited()
	g.dfs(g.findNode(numRows * numCols))
	for n in range(1, numRows * numCols + 1):
		if n not in g.dfslist:
			weGood = False
			break
	if weGood:
		print('YES')
	else:
		print('NO')


vals = input().split()
(n, m) = (int(vals[0]), int(vals[1]))
rows = input().split()[0]
cols = input().split()[0]
graph = {}
for r in range(n):
	for c in range(m):
		curr = r * m + c
		graph[curr] = []
		r_dir = rows[r]
		if r_dir == '<' and c != 0:
			graph[curr].append(curr - 1)
		elif r_dir == '>' and c != m - 1:
			graph[curr].append(curr + 1)
		c_dir = cols[c]
		if c_dir == '^' and r != 0:
			graph[curr].append(curr - m)
		elif c_dir == 'v' and r != n - 1:
			graph[curr].append(curr + m)
visited = set()
toVisit = [0]
while toVisit:
	curr = toVisit.pop()
	for u in graph[curr]:
		if u not in visited:
			visited.add(u)
			toVisit.append(u)
if len(visited) != n * m:
	print('NO')
else:
	print('YES')


(n, m) = map(int, input().split())
x = input()
y = input()
resp = x[0] + y[-1] + x[-1] + y[0]
if resp in ('>v<^', '<^>v'):
	print('YES')
else:
	print('NO')


def dfs(u, k, col):
	mark[u][k] = True
	for i in range(len(a[u][k])):
		if mark[a[u][k][i][0]][a[u][k][i][1]] == False:
			dfs(a[u][k][i][0], a[u][k][i][1], col)
	color[u][k] = col
(n, m) = map(int, input().split())
s = input()
a = [[[] for i in range(m)] for i in range(n)]
color = [[0] * m for i in range(n)]
col = 0
mark = [[False] * m for i in range(n)]
for i in range(len(s)):
	if s[i] == '<':
		for j in range(m - 1, 0, -1):
			a[i][j].append([i, j - 1])
	if s[i] == '>':
		for j in range(0, m - 1):
			a[i][j].append([i, j + 1])
t = input()
for j in range(len(t)):
	if t[j] == '^':
		for i in range(n - 1, 0, -1):
			a[i][j].append([i - 1, j])
	if t[j] == 'v':
		for i in range(0, n - 1):
			a[i][j].append([i + 1, j])
c1 = 0
for i in range(len(color)):
	for j in range(len(color[i])):
		color = [[0] * m for i in range(n)]
		mark = [[False] * m for i in range(n)]
		col = 1
		dfs(i, j, col)
		for r in range(len(color)):
			if 0 in color[r]:
				c1 = -1
if c1 == 0:
	print('YES')
else:
	print('NO')


import sys
input = sys.stdin.readline
from collections import defaultdict
(n, m) = map(int, input().split())
v = list(input().strip())
h = list(input().strip())
graph = defaultdict(list)
trans = defaultdict(list)
nodes = [[0] * m for _ in range(n)]
for i in range(n):
	if v[i] == '>':
		for j in range(m - 1):
			graph[i, j].append((i, j + 1))
		for j in range(m - 1, 0, -1):
			trans[i, j].append((i, j - 1))
	else:
		for j in range(m - 1, 0, -1):
			graph[i, j].append((i, j - 1))
		for j in range(m - 1):
			trans[i, j].append((i, j + 1))
for j in range(m):
	if h[j] == '^':
		for i in range(n - 1, 0, -1):
			graph[i, j].append((i - 1, j))
		for i in range(n - 1):
			trans[i, j].append((i + 1, j))
	else:
		for i in range(n - 1):
			graph[i, j].append((i + 1, j))
		for i in range(n - 1, 0, -1):
			trans[i, j].append((i - 1, j))
s = set()

def dfs(node, graph):
	s.add(node)
	for i in graph[node]:
		if i not in s:
			dfs(i, graph)
dfs((0, 0), graph)
if len(s) == m * n:
	s = set()
	dfs((0, 0), trans)
	if len(s) == m * n:
		print('YES')
	else:
		print('NO')
else:
	print('NO')


(h, w) = map(int, input().split())
go = [[[] for x in range(w)] for y in range(h)]
s = input()
t = input()
c1 = s[0] == '<' and s[h - 1] == '>' and (t[0] == 'v') and (t[w - 1] == '^')
c2 = s[0] == '>' and s[h - 1] == '<' and (t[0] == '^') and (t[w - 1] == 'v')
print('YES' if c1 or c2 else 'NO')


def main():
	(h, v) = (int(s) for s in input().split())
	east_west = input()
	north_south = input()
	(horizontal, vertical) = ([], [])
	for i in range(max(h, v)):
		if i < len(east_west):
			horizontal.append(east_west[i])
		if i < len(north_south):
			vertical.append(north_south[i])
	solve(horizontal, vertical)

def solve(horizontal, vertical):
	EAST_WEST = '<'
	SOUTH_NORTH = '^'
	if horizontal and vertical:
		if horizontal[-1] != EAST_WEST and vertical[-1] != SOUTH_NORTH:
			print('NO')
		elif horizontal[-1] == EAST_WEST and vertical[0] != SOUTH_NORTH:
			print('NO')
		elif horizontal[0] == EAST_WEST and vertical[0] == SOUTH_NORTH:
			print('NO')
		elif horizontal[0] != EAST_WEST and vertical[-1] == SOUTH_NORTH:
			print('NO')
		else:
			print('YES')
main()


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
(n, m) = map(int, input().split())
s = input()
s1 = input()
if s[0] == '>' and s[n - 1] == '<' and (s1[0] == '^') and (s1[m - 1] == 'v'):
	print('YES')
elif s[0] == '<' and s[n - 1] == '>' and (s1[0] == 'v') and (s1[m - 1] == '^'):
	print('YES')
else:
	print('NO')