You are given a connected undirected graph consisting of $n$ vertices and $m$ edges. There are no self-loops or multiple edges in the given graph.

You have to direct its edges in such a way that the obtained directed graph does not contain any paths of length two or greater (where the length of path is denoted as the number of traversed edges).


-----Input-----

The first line contains two integer numbers $n$ and $m$ ($2 \le n \le 2 \cdot 10^5$, $n - 1 \le m \le 2 \cdot 10^5$) — the number of vertices and edges, respectively.

The following $m$ lines contain edges: edge $i$ is given as a pair of vertices $u_i$, $v_i$ ($1 \le u_i, v_i \le n$, $u_i \ne v_i$). There are no multiple edges in the given graph, i. e. for each pair ($u_i, v_i$) there are no other pairs ($u_i, v_i$) and ($v_i, u_i$) in the list of edges. It is also guaranteed that the given graph is connected (there is a path between any pair of vertex in the given graph).


-----Output-----

If it is impossible to direct edges of the given graph in such a way that the obtained directed graph does not contain paths of length at least two, print "NO" in the first line.

Otherwise print "YES" in the first line, and then print any suitable orientation of edges: a binary string (the string consisting only of '0' and '1') of length $m$. The $i$-th element of this string should be '0' if the $i$-th edge of the graph should be directed from $u_i$ to $v_i$, and '1' otherwise. Edges are numbered in the order they are given in the input.


-----Example-----
Input
6 5
1 5
2 1
1 4
3 1
6 1

Output
YES
10100



-----Note-----

The picture corresponding to the first example: [Image]

And one of possible answers: $\text{of}$

Difficulty: MEDIUM_HARD

Solutions:
import os
from collections import deque, defaultdict

def isbipartite(col, g):
	col[1] = 0
	q = deque()
	q.append(1)
	bipartite = True
	while q:
		v = q.popleft()
		for i in range(0, len(g[v])):
			if col[g[v][i]] == -1:
				col[g[v][i]] = col[v] ^ 1
				q.append(g[v][i])
			else:
				bipartite = bipartite & (col[g[v][i]] != col[v])
	return bipartite

def main():
	N = 200100
	g = defaultdict(list)
	col = [-1] * N
	src = []
	dest = []
	(n, m) = map(int, input().split(' '))
	for i in range(0, m):
		(s, d) = map(int, input().split(' '))
		g[s].append(d)
		g[d].append(s)
		src.append(s)
		dest.append(d)
	edges = list(zip(src, dest))
	if not isbipartite(col, g):
		print('NO')
		exit(0)
	ans = ''
	for i in range(0, m):
		if col[edges[i][0]] == 0:
			ans = ans + '1'
		else:
			ans = ans + '0'
	print('YES')
	print(ans)
main()


(n, m) = map(int, input().split())
g = [False] * (n + 1)
t = [False] * (n + 1)
ide = {}
graf = []
for i in range(n):
	ide[i + 1] = []
for i in range(m):
	(u, v) = map(int, input().split())
	graf.append((u, v))
	ide[u].append(v)
	ide[v].append(u)
ch = [False] * (n + 1)
ifb = [1]
fr = 0
while fr < len(ifb):
	u = ifb[fr]
	ch[u] = True
	for v in ide[u]:
		if ch[v]:
			continue
		ifb.append(v)
		if g[u] and g[v] or (t[u] and t[v]):
			print('NO')
			exit()
		if g[u] and t[v] or (t[u] and g[v]):
			continue
		if g[u]:
			t[v] = True
			continue
		if t[u]:
			g[v] = True
			continue
		if g[v]:
			t[u] = True
			continue
		if t[v]:
			g[u] = True
			continue
		g[u] = True
		t[v] = True
	fr += 1
print('YES')
for (u, v) in graf:
	if g[u] and t[v]:
		print(1, end='')
	else:
		print(0, end='')
print()


from collections import defaultdict as DD
from bisect import bisect_left as BL
from bisect import bisect_right as BR
from itertools import combinations as IC
from itertools import permutations as IP
from random import randint as RI
import sys
MOD = pow(10, 9) + 7

def IN(f=0):
	if f == 0:
		return [int(i) for i in sys.stdin.readline().split()]
	else:
		return int(sys.stdin.readline())

def bfs(s):
	i = 1
	parent[s] = -1
	vis[s] = 1
	frontier = [s]
	while frontier:
		nex = []
		for u in frontier:
			for v in d[u]:
				if vis[v] == 0:
					vis[v] = 1
					color[v] = color[u] ^ 1
					parent[v] = u
					nex.append(v)
		frontier = nex
		i += 1
	return parent
(n, m) = IN()
d = DD(list)
d1 = []
for i in range(m):
	(u, v) = IN()
	d[u].append(v)
	d[v].append(u)
	d1.append([u, v])
vis = [0 for i in range(n + 1)]
color = [0 for i in range(n + 1)]
parent = dict()
for i in range(1, n + 1):
	if vis[i] == 0:
		bfs(i)
flag = 0
for i in d:
	for j in d[i]:
		if color[j] != color[i] ^ 1:
			flag = 1
			break
	if flag == 1:
		break
if flag == 1:
	print('NO')
else:
	ans = ''
	for (i, j) in d1:
		if color[i] == 0 and color[j] == 1:
			ans += str(1)
		else:
			ans += str(0)
	print('YES')
	print(ans)


import math
import bisect

def egcd(a, b):
	if a == 0:
		return (b, 0, 1)
	else:
		(g, x, y) = egcd(b % a, a)
		return (g, y - b // a * x, x)

def mulinv(b, n):
	(g, x, _) = egcd(b, n)
	if g == 1:
		return x % n
primes = []

def isprime(n):
	for d in range(2, int(math.sqrt(n)) + 1):
		if n % d == 0:
			return False
	return True

def argsort(ls):
	return sorted(range(len(ls)), key=ls.__getitem__)

def f(p=0):
	if p == 1:
		return map(int, input().split())
	elif p == 2:
		return list(map(int, input().split()))
	else:
		return int(input())
(n, m) = f(1)
g = [list() for _ in range(n + 1)]
ver = [-1] * (n + 1)
dl = [-1] * m
edges = [0] * m
vdl = [0] * (n + 1)
for i in range(m):
	(u, v) = f(1)
	g[u].append(i)
	g[v].append(i)
	edges[i] = (u, v)
queue = [1]
orient = 1
ver[1] = 1
for i in range(1, n + 1):
	if vdl[i] == 0:
		vdl[i] = 1
		queue = [i]
		ver[i] = 0
		for u in queue:
			for edge in g[u]:
				pos = 0
				if edges[edge][0] == u:
					pos = 0
				else:
					pos = 1
				if ver[u] == ver[edges[edge][(pos + 1) % 2]]:
					print('NO')
					exit()
				else:
					e = 0
					if ver[u] == 0:
						if pos == 0:
							e = 1
						else:
							e = 0
					elif pos == 0:
						e = 0
					else:
						e = 1
					if dl[edge] != -1 and dl[edge] != e:
						print('NO')
						exit()
					else:
						dl[edge] = e
				if vdl[edges[edge][(pos + 1) % 2]] != 1:
					queue.append(edges[edge][(pos + 1) % 2])
					ver[edges[edge][(pos + 1) % 2]] = (ver[u] + 1) % 2
					vdl[edges[edge][(pos + 1) % 2]] = 1
print('YES')
print(''.join((str(el) for el in dl)))


import sys

def input():
	return sys.stdin.readline()
(n, m) = map(int, input().split())
give = [False] * (n + 1)
take = [False] * (n + 1)
edge = dict()
inputs = []
for i in range(n):
	edge[i + 1] = []
for i in range(m):
	(u, v) = map(int, input().split())
	inputs.append((u, v))
	edge[u].append(v)
	edge[v].append(u)
check = [False] * (n + 1)
queue = [1]
front = 0
while front < len(queue):
	u = queue[front]
	check[u] = True
	for v in edge[u]:
		if check[v]:
			continue
		queue.append(v)
		if give[u] and give[v] or (take[u] and take[v]):
			print('NO')
			return
		if give[u] and take[v] or (take[u] and give[v]):
			continue
		if give[u]:
			take[v] = True
			continue
		if take[u]:
			give[v] = True
			continue
		if give[v]:
			take[u] = True
			continue
		if take[v]:
			give[u] = True
			continue
		give[u] = True
		take[v] = True
	front += 1
print('YES')
for (u, v) in inputs:
	if give[u] and take[v]:
		print(1, end='')
	else:
		print(0, end='')
print()


from collections import deque
(n, m) = map(int, input().split())
g = [[] for i in range(n)]
e = []
for tc in range(m):
	(u, v) = map(int, input().split())
	u -= 1
	v -= 1
	e.append((u, v))
	g[u].append(v)
	g[v].append(u)
p = [-1] * n
p[0] = True
yes = True
q = deque([0])
while q:
	f = q.popleft()
	for t in g[f]:
		if p[t] == -1:
			q.append(t)
			p[t] = not p[f]
		elif p[t] == p[f]:
			yes = False
if not yes:
	print('NO')
else:
	print('YES')
	print(''.join(('1' if p[e[i][0]] else '0' for i in range(m))))


from collections import deque

def solve():
	(n, m) = input().split()
	n = int(n)
	m = int(m)
	global max
	max = n * 2
	graph = [[] for _ in range(0, n)]
	distance = [max] * n
	edges = []
	for _ in range(0, m):
		(u, v) = input().split()
		u = int(u) - 1
		v = int(v) - 1
		edges.append(v)
		graph[u].append(v)
		graph[v].append(u)
	if bfs_2k(graph, 0, distance):
		print('YES')
		print(''.join((str(distance[e] % 2) for e in edges)))
	else:
		print('NO')

def bfs_2k(graph, initVertex, dist):
	queue = deque()
	queue.append(initVertex)
	dist[initVertex] = 0
	while queue:
		u = queue.popleft()
		for v in graph[u]:
			if dist[v] == max:
				dist[v] = dist[u] + 1
				queue.append(v)
			if (dist[u] - dist[v]) % 2 == 0:
				return False
	return True
solve()


(n, m) = map(int, input().split())
graph = [[] for _ in range(n)]
ind = 0
for e in range(m):
	(a, b) = map(int, input().split())
	graph[a - 1].append((b - 1, ind, True))
	graph[b - 1].append((a - 1, ind, False))
	ind = ind + 1
paint_array = [-1 for _ in range(n)]
visited = [0 for _ in range(m + 1)]

def paint(vi, color):
	paint_array[vi] = color
	visited[0] = vi
	start = 0
	finish = 1
	paint_ok = True
	while finish != start and paint_ok:
		v = visited[start]
		start = (start + 1) % (m + 1)
		c = paint_array[v]
		for (vi2, ind, orig) in graph[v]:
			if paint_array[vi2] != -1 and paint_array[vi2] != 1 - c:
				paint_ok = False
				break
			if paint_array[vi2] == -1:
				paint_array[vi2] = 1 - c
				visited[finish] = vi2
				finish = (finish + 1) % (m + 1)
	return paint_ok
ok = True
for vi in range(n):
	if paint_array[vi] == -1:
		ok = ok and paint(vi, 0)
if not ok:
	print('NO')
	exit(0)
print('YES')
result = [0 for _ in range(m)]
for vi in range(n):
	for (vi2, ind, orig) in graph[vi]:
		if orig:
			result[ind] = paint_array[vi]
for i in range(m):
	print('0' if result[i] else '1', end='')


graph = [[] for _ in range(200000)]
color = [0] * 200000
vis = [0] * 200000

def main():
	(n, m) = map(int, input().split())
	edges = []
	for _ in range(m):
		(u, v) = map(int, input().split())
		u -= 1
		v -= 1
		graph[u].append(v)
		graph[v].append(u)
		edges.append((u, v))
	color[0] = 1
	queue = [(0, 1)]
	i = 0
	while i != len(queue):
		for v in graph[queue[i][0]]:
			if not color[v]:
				color[v] = 3 - queue[i][1]
				queue.append((v, color[v]))
		i += 1
	ans = ['0'] * m
	for i in range(m):
		if color[edges[i][0]] == color[edges[i][1]]:
			print('NO')
			return 0
		if color[edges[i][0]] == 1:
			ans[i] = '1'
	print('YES')
	print(''.join(ans))
main()


import sys
import math
import bisect
from sys import stdin, stdout
from math import gcd, floor, sqrt, log
from collections import defaultdict as dd, deque
from bisect import bisect_left as bl, bisect_right as br
sys.setrecursionlimit(100000000)
inp = lambda : int(input())
strng = lambda : input().strip()
jn = lambda x, l: x.join(map(str, l))
strl = lambda : list(input().strip())
mul = lambda : map(int, input().strip().split())
mulf = lambda : map(float, input().strip().split())
seq = lambda : list(map(int, input().strip().split()))
ceil = lambda x: int(x) if x == int(x) else int(x) + 1
ceildiv = lambda x, d: x // d if x % d == 0 else x // d + 1
flush = lambda : stdout.flush()
stdstr = lambda : stdin.readline()
stdint = lambda : int(stdin.readline())
stdpr = lambda x: stdout.write(str(x))
mod = 1000000007
(n, m) = mul()
Adj = [[] for _ in range(n + 1)]
Edges = []
for _ in range(m):
	(u, v) = mul()
	Edges.append((u, v))
	Adj[u].append(v)
	Adj[v].append(u)
Side = [-1] * (n + 1)
Q = deque()
isbipartite = True
for i in range(1, n + 1):
	if Side[i] == -1:
		Q.append(i)
		Side[i] = 1
		while len(Q):
			u = Q.pop()
			for v in Adj[u]:
				if Side[v] == -1:
					Side[v] = Side[u] ^ 1
					Q.append(v)
				else:
					isbipartite &= Side[v] != Side[u]
if not isbipartite:
	print('NO')
else:
	print('YES')
	S = ''
	for (u, v) in Edges:
		if Side[u] == 0:
			S += '0'
		else:
			S += '1'
	print(S)


import sys
from collections import deque
input = sys.stdin.readline
(n, m) = map(int, input().split())
EDGE = [list(map(int, input().split())) for i in range(m)]
EDGELIST = [[] for i in range(n + 1)]
for (x, y) in EDGE:
	EDGELIST[x].append(y)
	EDGELIST[y].append(x)
QUE = deque([[1, 1]])
ANS = [-1] * (n + 1)
ANS[1] = 1
while QUE:
	(x, color) = QUE.pop()
	ANS[x] = color
	for to in EDGELIST[x]:
		if ANS[to] == color:
			print('NO')
			return
		if ANS[to] == -1:
			QUE.appendleft([to, abs(color - 1)])
print('YES')
for (x, y) in EDGE:
	if ANS[x] == 1:
		print('1', end='')
	else:
		print('0', end='')


from collections import deque

def isBipartiate(adj, color):
	flip = {0: 1, 1: 0}
	for node in range(1, n + 1):
		if color[node] == -1:
			color[node] = 1
			qu = deque()
			qu.append(node)
			while qu:
				node = qu.popleft()
				for neigh in adj[node]:
					if color[neigh] == -1:
						color[neigh] = flip[color[node]]
						qu.append(neigh)
					elif color[neigh] == color[node]:
						return False
	return True
from collections import defaultdict
(n, m) = map(int, input().split())
adj = defaultdict(list)
edges = []
for _ in range(m):
	(u, v) = map(int, input().split())
	adj[u].append(v)
	adj[v].append(u)
	edges.append([u, v])
color = [-1] * (n + 1)
if not isBipartiate(adj, color):
	print('NO')
else:
	print('YES')
	for i in range(m):
		print(color[edges[i][0]], end='')


import sys
sys.setrecursionlimit(10000000)
(a, b) = tuple([int(i) for i in input().split()])
save = {}
printl = [''] * b
data = ['']
for i in range(a):
	data.append(set())
for i in range(b):
	a = input().split()
	c = int(a[0])
	d = int(a[1])
	save[c, d] = i
	data[c].add(d)
	data[d].add(c)
done = set()

def search(prev, a, isforward):
	if isforward:
		good = '1'
		bad = '0'
	else:
		good = '0'
		bad = '1'
	for e in data[a]:
		if e in done or e == prev:
			continue
		if (a, e) in save:
			p = save[a, e]
			if printl[p] != '':
				if printl[p] != good:
					print('NO')
					sys.exit()
			else:
				printl[p] = good
				search(a, e, not isforward)
		else:
			p = save[e, a]
			if printl[p] != '':
				if printl[p] != bad:
					print('NO')
					sys.exit()
			else:
				printl[p] = bad
				search(a, e, not isforward)
	done.add(a)
layer = {1}
good = '0'
bad = '1'
while len(layer) > 0:
	(good, bad) = (bad, good)
	new = set()
	for a in layer:
		for e in data[a]:
			if (a, e) in save:
				p = save[a, e]
				if printl[p] != '':
					if printl[p] != good:
						print('NO')
						sys.exit()
				else:
					printl[p] = good
					new.add(e)
			else:
				p = save[e, a]
				if printl[p] != '':
					if printl[p] != bad:
						print('NO')
						sys.exit()
				else:
					printl[p] = bad
					new.add(e)
		layer = new
print('YES')
print(''.join(printl))


import sys, bisect, string, math, time, functools, random, fractions
from heapq import heappush, heappop, heapify
from collections import deque, defaultdict, Counter
from itertools import permutations, combinations, groupby
rep = range
R = range

def Golf():
	(n, *t) = map(int, open(0).read().split())

def I():
	return int(input())

def S_():
	return input()

def IS():
	return input().split()

def LS():
	return [i for i in input().split()]

def MI():
	return map(int, input().split())

def LI():
	return [int(i) for i in input().split()]

def LI_():
	return [int(i) - 1 for i in input().split()]

def NI(n):
	return [int(input()) for i in range(n)]

def NI_(n):
	return [int(input()) - 1 for i in range(n)]

def StoLI():
	return [ord(i) - 97 for i in input()]

def ItoS(n):
	return chr(n + 97)

def LtoS(ls):
	return ''.join([chr(i + 97) for i in ls])

def RA():
	return map(int, open(0).read().split())

def RLI(n=8, a=1, b=10):
	return [random.randint(a, b) for i in range(n)]

def RI(a=1, b=10):
	return random.randint(a, b)

def Rtest(T):
	(case, err) = (0, 0)
	for i in range(T):
		inp = INP()
		(a1, ls) = naive(*inp)
		a2 = solve(*inp)
		if a1 != a2:
			print((a1, a2), inp)
			err += 1
		case += 1
	print('Tested', case, 'case with', err, 'errors')

def GI(V, E, ls=None, Directed=False, index=1):
	org_inp = []
	g = [[] for i in range(V)]
	FromStdin = True if ls == None else False
	for i in range(E):
		if FromStdin:
			inp = LI()
			org_inp.append(inp)
		else:
			inp = ls[i]
		if len(inp) == 2:
			(a, b) = inp
			c = 1
		else:
			(a, b, c) = inp
		if index == 1:
			a -= 1
			b -= 1
		aa = (a, c)
		bb = (b, c)
		g[a].append(bb)
		if not Directed:
			g[b].append(aa)
	return (g, org_inp)

def GGI(h, w, search=None, replacement_of_found='.', mp_def={'#': 1, '.': 0}, boundary=1):
	mp = [boundary] * (w + 2)
	found = {}
	for i in R(h):
		s = input()
		for char in search:
			if char in s:
				found[char] = (i + 1) * (w + 2) + s.index(char) + 1
				mp_def[char] = mp_def[replacement_of_found]
		mp += [boundary] + [mp_def[j] for j in s] + [boundary]
	mp += [boundary] * (w + 2)
	return (h + 2, w + 2, mp, found)

def TI(n):
	return GI(n, n - 1)

def accum(ls):
	rt = [0]
	for i in ls:
		rt += [rt[-1] + i]
	return rt

def bit_combination(n, base=2):
	rt = []
	for tb in R(base ** n):
		s = [tb // base ** bt % base for bt in R(n)]
		rt += [s]
	return rt

def gcd(x, y):
	if y == 0:
		return x
	if x % y == 0:
		return y
	while x % y != 0:
		(x, y) = (y, x % y)
	return y

def YN(x):
	print(['NO', 'YES'][x])

def Yn(x):
	print(['No', 'Yes'][x])

def show(*inp, end='\n'):
	if show_flg:
		print(*inp, end=end)
mo = 10 ** 9 + 7
inf = float('inf')
FourNb = [(-1, 0), (1, 0), (0, 1), (0, -1)]
EightNb = [(-1, 0), (1, 0), (0, 1), (0, -1), (1, 1), (-1, -1), (1, -1), (-1, 1)]
compas = dict(zip('WENS', FourNb))
cursol = dict(zip('LRUD', FourNb))
l_alp = string.ascii_lowercase
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
input = lambda : sys.stdin.readline().rstrip()
show_flg = False
show_flg = True
ans = 0
ans = []
(n, m) = LI()
(g, org) = GI(n, m)
v = [-1 for i in range(n)]

def IsBipartite(edge):
	q = [0]
	v[0] = 0
	while q:
		c = q.pop()
		for (n, d) in edge[c]:
			if v[n] == -1:
				q.append(n)
				v[n] = 1 - v[c]
			elif v[n] == v[c]:
				return (False, [])
	return (True, v)
(ans, v) = IsBipartite(g)
if ans:
	YN(1)
	for (s, t) in org:
		print(v[t - 1], end='')
	print()
else:
	YN(0)


from collections import defaultdict, deque
import bisect
import sys
input = sys.stdin.readline

def bfs(root):
	queue = deque()
	queue.append((root, 0))
	while queue:
		(vertex, dir_) = queue.popleft()
		for child in graph[vertex]:
			if ans[child[0]] == -1:
				ans[child[0]] = 1 - dir_
				queue.append((child[0], 1 - dir_))
			elif ans[child[0]] == dir_:
				print('NO')
				exit()
graph = defaultdict(list)
(n, m) = map(int, input().split())
direction = []
for i in range(m):
	(u, v) = map(int, input().split())
	graph[u].append([v, i])
	graph[v].append([u, i])
	direction.append([u, v])
ans = [-1] * (n + 1)
bfs(1)
output = [0] * m
for i in range(1, n + 1):
	if ans[i] == 1:
		for j in graph[i]:
			if direction[j[1]] == [j[0], i]:
				output[j[1]] = 1
			else:
				output[j[1]] = 0
print('YES')
print(''.join(map(str, output)))


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')
from collections import deque
edge = []

def graph_undirected():
	(n, e) = [int(x) for x in input().split()]
	graph = {}
	for i in range(e):
		(vertex, neighbour) = [int(x) for x in input().split()]
		edge.append([vertex, neighbour])
		if vertex in graph:
			graph[vertex].append(neighbour)
		else:
			graph[vertex] = [neighbour]
		if neighbour in graph:
			graph[neighbour].append(vertex)
		else:
			graph[neighbour] = [vertex]
	return (graph, n)
(graph, n) = graph_undirected()
visited = [False for x in range(n + 1)]
color = [None for x in range(n + 1)]

def cycle_bfs(graph, n, node):
	q = deque([node])
	color[node] = 0
	while q:
		currnode = q.popleft()
		visited[currnode] = True
		if color[currnode] == 0:
			currcolor = 1
		else:
			currcolor = 0
		if currnode in graph:
			for neighbour in graph[currnode]:
				if visited[neighbour] == False:
					visited[neighbour] = True
					color[neighbour] = currcolor
					q.append(neighbour)
				elif color[neighbour] != currcolor:
					return False
	return True
for node in range(1, n + 1):
	if visited[n] == False:
		ans = cycle_bfs(graph, n, node)
		if ans == False:
			break
if ans == True:
	print('YES')
	for (u, v) in edge:
		if color[u] == 1:
			print('0', end='')
		else:
			print('1', end='')
else:
	print('NO')


import sys
input = sys.stdin.readline
from collections import deque

def bfs():
	q = deque([0])
	color[0] = 1
	while q:
		v = q.popleft()
		for nv in adj_list[v]:
			if color[nv] == 0:
				color[nv] = -color[v]
				q.append(nv)
			elif color[nv] == color[v]:
				return False
	return True
(n, m) = map(int, input().split())
adj_list = [[] for _ in range(n)]
edges = []
for _ in range(m):
	(u, v) = map(int, input().split())
	adj_list[u - 1].append(v - 1)
	adj_list[v - 1].append(u - 1)
	edges.append((u - 1, v - 1))
color = [0] * n
if not bfs():
	print('NO')
	exit()
ans = []
for (u, v) in edges:
	if color[u] == 1 and color[v] == -1:
		ans.append('1')
	else:
		ans.append('0')
print('YES')
print(''.join(ans))


from typing import List
from collections import defaultdict

class GraphColoring:

	def isTwoColorable(self, edges, numVertices):
		graph = defaultdict(list)
		for (a, b) in edges:
			a = a - 1
			b = b - 1
			na = graph[a]
			nb = graph[b]
			na.append(b)
			nb.append(a)
			graph[a] = na
			graph[b] = nb
		visited = [None] * numVertices
		for v in range(numVertices):
			if visited[v] is not None:
				continue
			q = [v]
			visited[v] = True
			while q:
				curr = q.pop()
				for ne in graph[curr]:
					if visited[ne] is not None:
						if visited[ne] == visited[curr]:
							return (False, [])
					else:
						visited[ne] = not visited[curr]
						q.append(ne)
		directions = [max(visited[a - 1] - visited[b - 1], 0) for (a, b) in edges]
		return (True, directions)
(n, m, *_) = map(int, input().split())
edges = []
for _ in range(m):
	(a, b, *_) = map(int, input().split())
	edges.append([a, b])
gc = GraphColoring()
(isTwoC, coloring) = gc.isTwoColorable(edges, n)
if isTwoC:
	print('YES')
	print(''.join(map(str, map(int, coloring))))
else:
	print('NO')


import sys
from typing import List, Tuple, Dict
DEBUG = len(sys.argv) > 1 and sys.argv[1] == '-d'

def LOG(*argv):
	if DEBUG:
		print(*argv, file=sys.stderr)

def CHECK(cond, err_msg=''):
	if DEBUG:
		assert cond, err_msg

def CHECK_EQ(a, b, err_msg=''):
	CHECK(a == b, err_msg='{} v.s. {} {}'.format(a, b, err_msg))

def readval(typ=int):
	return typ(input())

def readvals(typ=int):
	return list(map(typ, input().split()))

def solve(n: int, m: int, edges: List[Tuple[int, int]]) -> str:
	from collections import defaultdict
	neighbors: Dict[int, List[int]] = defaultdict(list)
	for (u, v) in edges:
		neighbors[u].append(v)
		neighbors[v].append(u)
	LOG('neighbors=', neighbors)
	color: Dict[int, bool] = {1: True}
	(queue, visited) = ([1], set([1]))
	cur_color = True
	while len(queue) > 0:
		next_queue = []
		next_color = not cur_color
		for node in queue:
			for next_node in neighbors[node]:
				if next_node not in visited:
					visited.add(next_node)
					next_queue.append(next_node)
					color[next_node] = next_color
		queue = next_queue
		cur_color = next_color
	solution = ''
	for (u, v) in edges:
		if color[u] == color[v]:
			return 'NO'
		solution += '1' if color[u] is True else '0'
	return f'YES\n{solution}'
(n, m) = readvals()
edges = [readvals() for _ in range(m)]
LOG('edges=', edges)
print(solve(n, m, edges))


from collections import deque

def bfs_2k(graph, initVertex, color):
	queue = deque()
	queue.append(initVertex)
	color[initVertex] = 0
	while queue:
		u = queue.popleft()
		for v in graph[u]:
			if color[v] == color[u]:
				return False
			if color[v] == -1:
				color[v] = color[u] ^ 1
				queue.append(v)
	return True
(n, m) = input().split()
n = int(n)
m = int(m)
graph = [[] for _ in range(0, n)]
color = [-1] * n
edges = []
for i in range(0, m):
	(u, v) = input().split()
	u = int(u) - 1
	v = int(v) - 1
	edges.append(v)
	graph[u].append(v)
	graph[v].append(u)
if bfs_2k(graph, 0, color):
	print('YES')
	print(''.join((str(color[e]) for e in edges)))
else:
	print('NO')


from collections import deque

def solve():
	global n, m
	(n, m) = map(lambda x: int(x), input().split())
	global maxValue
	maxValue = n ** 2
	graph = [[] for _ in range(0, n)]
	edges = []
	for _ in range(0, m):
		(u, v) = map(lambda x: int(x) - 1, input().split())
		graph[u].append(v)
		graph[v].append(u)
		edges.append(v)
	distance = bfs_2k(graph, 0)
	if distance is None:
		print('NO')
	else:
		print('YES')
		print(''.join((str(distance[e] % 2) for e in edges)))

def bfs_2k(graph, initVertex):
	dist = [maxValue] * n
	queue = deque()
	queue.append(initVertex)
	dist[initVertex] = 0
	while queue:
		u = queue.popleft()
		for v in graph[u]:
			if dist[v] == maxValue:
				dist[v] = dist[u] + 1
				queue.append(v)
			elif (dist[u] - dist[v]) % 2 == 0:
				return None
	return dist
solve()


from collections import deque

class Graph:

	def __init__(self, nvertices):
		self.nvertices = nvertices
		self.adj_list = [[] for v in range(nvertices + 1)]
		self.edges = []

	def add_edge(self, edge):
		self.edges.append(edge)

	def get_neighbors(self, ind):
		return self.adj_list[ind]

	def add_neighbor(self, vert, neighbor):
		self.adj_list[vert].append(neighbor)

	def print_graph(self):
		for (ind, vert) in enumerate(self.adj_list):
			if ind == 0:
				continue
			print(ind, '-->', vert)

def solve(graph):
	queue = set([(1, 0)])
	visited = [False] * (graph.nvertices + 1)
	marks = [None] * (graph.nvertices + 1)
	marks[1] = 0
	while len(queue):
		(vert, mark) = queue.pop()
		visited[vert] = True
		for neighbor in graph.get_neighbors(vert):
			if visited[neighbor] == False:
				queue.add((neighbor, not mark))
				marks[neighbor] = not mark
			elif marks[neighbor] == mark:
				print('NO')
				return
	print('YES')
	result = ''
	for (v1, v2) in graph.edges:
		if marks[v1] > marks[v2]:
			result += '0'
		else:
			result += '1'
	print(result)

def get_input():
	(nvertices, nedges) = list(map(int, input().split()))
	graph = Graph(nvertices)
	for edge in range(nedges):
		(v1, v2) = list(map(int, input().split()))
		graph.add_neighbor(v1, v2)
		graph.add_neighbor(v2, v1)
		graph.add_edge((v1, v2))
	return graph
graph = get_input()
solve(graph)


from collections import deque
import sys
input = sys.stdin.readline

def bfs(s):
	q = deque()
	q.append(s)
	dist = [-1] * (n + 1)
	dist[s] = 0
	ans = [0] * m
	while q:
		i = q.popleft()
		nd = dist[i] + 1
		for j in G[i]:
			if dist[j] == -1:
				dist[j] = nd
				q.append(j)
				if nd % 2:
					if (i, j) in d:
						ans[d[i, j]] = '1'
					else:
						ans[d[j, i]] = '0'
				elif (i, j) in d:
					ans[d[i, j]] = '0'
				else:
					ans[d[j, i]] = '1'
			else:
				if dist[j] % 2 ^ nd % 2:
					ans = 'NO'
					print(ans)
					exit()
				if nd % 2:
					if (i, j) in d:
						ans[d[i, j]] = '1'
					else:
						ans[d[j, i]] = '0'
				elif (i, j) in d:
					ans[d[i, j]] = '0'
				else:
					ans[d[j, i]] = '1'
	return ans
(n, m) = map(int, input().split())
G = [[] for _ in range(n + 1)]
d = dict()
for i in range(m):
	(u, v) = map(int, input().split())
	G[u].append(v)
	G[v].append(u)
	d[u, v] = i
ans = bfs(1)
print('YES')
print(''.join(ans))


from collections import deque
from math import inf as infinity

def solve():
	global n, m
	(n, m) = map(lambda x: int(x), input().split())
	graph = [[] for _ in range(0, n)]
	edges = [-1] * m
	for i in range(0, m):
		(u, v) = map(lambda x: int(x) - 1, input().split())
		graph[u].append(v)
		graph[v].append(u)
		edges[i] = v
	distance = bfs_2k(graph, 0)
	if distance is None:
		print('NO')
	else:
		print('YES')
		print(''.join((str(distance[e] % 2) for e in edges)))

def bfs_2k(graph, s):
	dist = [infinity] * n
	queue = deque()
	queue.append(s)
	dist[s] = 0
	while queue:
		u = queue.popleft()
		for v in graph[u]:
			if dist[v] == infinity:
				dist[v] = dist[u] + 1
				queue.append(v)
			elif (dist[u] - dist[v]) % 2 == 0:
				return None
	return dist
solve()


from sys import stdin
from collections import deque
input = stdin.readline

def solve():
	visited = [False] * (n + 1)
	direction = [True] * (n + 1)
	visited[1] = True
	queue = deque()
	queue.append(1)
	while queue:
		node = queue.popleft()
		for neighbor in g[node]:
			if visited[neighbor]:
				if direction[node] == direction[neighbor]:
					print('NO')
					return
			else:
				visited[neighbor] = True
				direction[neighbor] = not direction[node]
				queue.append(neighbor)
	ans = []
	for (u, v) in a:
		ans.append(int(direction[u]))
	print('YES')
	print(*ans, sep='')
(n, m) = [int(x) for x in input().split()]
g = [[] for _ in range(n + 1)]
a = []
for _ in range(m):
	(u, v) = [int(x) for x in input().split()]
	g[u].append(v)
	g[v].append(u)
	a.append((u, v))
solve()


arr = input()
(N, E) = [int(x) for x in arr.split(' ')]
edges = [[0] * 2 for _ in range(E)]
edge_list = [[] for _ in range(N + 1)]
ans = {}
for i in range(E):
	s = input()
	(u, v) = [int(x) for x in s.split(' ')]
	edges[i][0] = u
	edges[i][1] = v
	edge_list[u].append(v)
	edge_list[v].append(u)
stack = [1]
ans = [-1] * (N + 1)
ans[1] = 1
cur = 1
flag = 0
while stack:
	p = stack.pop()
	cur = ans[p]
	for num in edge_list[p]:
		if ans[num] == -1:
			stack.append(num)
			ans[num] = cur ^ 1
		elif ans[num] == cur:
			flag = 1
			print('NO')
			quit()
if flag == 1:
	print('NO')
else:
	print('YES')
	for i in range(E):
		u = edges[i][0]
		print(ans[u], end='')


from collections import deque

def dfs_2k(graph, initNode, visited, color):
	stack = deque()
	stack.append(initNode)
	color[initNode] = 0
	while stack:
		u = stack.pop()
		visited[u] = True
		for v in graph[u]:
			if color[v] == color[u]:
				return False
			if not visited[v]:
				color[v] = color[u] ^ 1
				stack.append(v)
	return True
(n, m) = input().split()
n = int(n)
m = int(m)
graph = []
edges = []
visited = [False] * n
color = [-1] * n
for i in range(0, n):
	graph.append([])
for i in range(0, m):
	(u, v) = input().split()
	u = int(u) - 1
	v = int(v) - 1
	edges.append(v)
	graph[u].append(v)
	graph[v].append(u)
if dfs_2k(graph, 0, visited, color):
	print('YES')
	print(''.join((str(color[e]) for e in edges)))
else:
	print('NO')


import os.path
from math import gcd, floor, ceil
from collections import *
import sys
from heapq import *
mod = 1000000007
INF = float('inf')

def st():
	return list(sys.stdin.readline().strip())

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

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

def inp():
	return int(sys.stdin.readline())

def pr(n):
	return sys.stdout.write(str(n) + '\n')

def prl(n):
	return sys.stdout.write(str(n) + ' ')
if os.path.exists('input.txt'):
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')

def solve():

	def dfs(x):
		stack = [x]
		v[x] = 1
		while stack:
			a = stack.pop()
			for i in d[a]:
				if v[i]:
					if color[i] == color[a]:
						pr('NO')
						exit()
				else:
					color[i] = color[a] ^ 1
					v[i] = 1
					stack.append(i)
	(n, m) = mp()
	d = defaultdict(list)
	l = []
	for i in range(m):
		(a, b) = mp()
		l.append([a, b])
		d[a].append(b)
		d[b].append(a)
	color = defaultdict(lambda : -1)
	color[1] = 0
	v = defaultdict(int)
	dfs(1)
	ans = []
	pr('YES')
	for i in l:
		(a, b) = i
		if color[a] == 0:
			ans.append('1')
		else:
			ans.append('0')
	print(*ans, sep='')
for _ in range(1):
	solve()


(n, m) = map(int, input().split())
clr = [-1 for i in range(0, n)]
eds = []

def dfs():
	cur = 0
	st = [-1 for i in range(0, n + 1)]
	st[cur] = 0
	cur += 1
	while cur > 0:
		v = st[cur - 1]
		cur -= 1
		for x in g[v]:
			if clr[x] != -1:
				if clr[x] == clr[v]:
					return False
				continue
			clr[x] = clr[v] ^ 1
			st[cur] = x
			cur += 1
	return True
g = [[] for i in range(0, n)]
for i in range(0, m):
	(u, v) = map(int, input().split())
	u -= 1
	v -= 1
	g[u].append(v)
	g[v].append(u)
	eds.append((u, v))
clr[0] = 0
if dfs():
	print('YES')
	print(''.join(('1' if clr[u] < clr[v] else '0' for (u, v) in eds)))
else:
	print('NO')


(n, m) = map(int, input().split(' '))
color = [-1 for i in range(n)]
neighbour = [[] for i in range(n)]
store = []
for i in range(m):
	(p, q) = map(int, input().split(' '))
	store.append([p - 1, q - 1])
	neighbour[p - 1].append(q - 1)
	neighbour[q - 1].append(p - 1)
ans = ''
flag = True
color[0] = 1
queue = []
queue.append(0)
while queue:
	u = queue.pop()
	for v in neighbour[u]:
		if color[v] == -1:
			color[v] = 1 - color[u]
			queue.append(v)
		elif color[v] == color[u]:
			print('NO')
			flag = False
			queue = []
			break
if flag:
	for i in store:
		if color[i[0]] == 1:
			ans += '1'
		else:
			ans += '0'
	print('YES')
	print(ans)


class UnionFind:

	def __init__(self, num_elements):
		self.parent = list(range(num_elements))
		self.rank = [1] * num_elements

	def union(self, a, b):
		par_a = self.find(a)
		par_b = self.find(b)
		if par_a == par_b:
			return
		if self.rank[par_a] > self.rank[par_b]:
			self.parent[par_b] = par_a
			self.rank[par_a] = self.rank[par_a] + self.rank[par_b]
		else:
			self.parent[par_a] = par_b
			self.rank[par_b] = self.rank[par_a] + self.rank[par_b]

	def find(self, a):
		if self.parent[a] == a:
			return a
		par_a = self.find(self.parent[a])
		curr_parent = self.parent[a]
		if par_a != curr_parent:
			self.rank[curr_parent] -= self.rank[a]
			self.parent[a] = par_a
		return par_a
(n, m) = map(int, input().split())
edges = [[] for i in range(n + 1)]
inp_edges = []
uf = UnionFind(n + 1)
for i in range(m):
	(u, v) = map(int, input().split())
	edges[u].append(v)
	edges[v].append(u)
	inp_edges.append((u, v))
possible = True
for i in range(1, n + 1):
	if len(edges[i]):
		node_parent = uf.find(i)
		first_parent = uf.find(edges[i][0])
		if first_parent == uf.find(i):
			possible = False
			break
		for neb in edges[i][1:]:
			parent = uf.find(neb)
			if parent == node_parent:
				possible = False
				break
			uf.union(first_parent, parent)
	if not possible:
		break
if not possible:
	print('NO')
else:
	print('YES')
	for i in range(1, n + 1):
		if len(edges[i]):
			first_parent = uf.find(i)
			break
	ans = []
	for e in inp_edges:
		if uf.find(e[0]) == first_parent:
			ans.append('1')
		else:
			ans.append('0')
	print(''.join(ans))


(n, m) = map(int, input().split())
gr = [[] for i in range(n)]
trr = []
for i in range(m):
	(u, v) = map(int, input().split())
	gr[u - 1].append(v - 1)
	gr[v - 1].append(u - 1)
	trr.append(v)
tr = {}
for i in range(n):
	tr[i] = -1
tr[0] = 0
s = set([0])
v = [False for i in range(n)]
t = True
while s and t:
	x = s.pop()
	k = 1 if tr[x] == 0 else 0
	v[x] = True
	for j in gr[x]:
		if v[j]:
			if tr[j] == k:
				continue
			else:
				t = False
				break
		else:
			tr[j] = k
			s.add(j)
if t:
	print('YES')
	s = ''
	for i in trr:
		s += str(tr[i - 1])
	print(s)
	exit()
tr = {}
for i in range(n):
	tr[i] = -1
tr[0] = 1
s = set([0])
v = [False for i in range(n)]
t = True
while s and t:
	x = s.pop()
	k = 1 if tr[x] == 0 else 0
	v[x] = True
	for j in gr[x]:
		if v[j]:
			if tr[j] == k:
				continue
			else:
				t = False
				break
		else:
			tr[j] = k
			s.add(j)
if t:
	print('YES')
	s = ''
	for i in trr:
		s += str(tr[i - 1])
	print(s)
	exit()
print('NO')


from collections import defaultdict

def main():
	(n, m) = map(int, input().split())
	roads = []
	graph = defaultdict(dict)
	for _ in range(m):
		(u, v) = map(int, input().split())
		roads.append((u, v))
		graph[u][v] = 1
		graph[v][u] = 1
	nodes = [-1 for _ in range(n + 1)]
	nodes[1] = 1
	stack = [1]
	while stack:
		cur = stack.pop()
		flag = nodes[cur]
		if flag:
			for i in graph[cur]:
				if graph[cur][i]:
					if nodes[i] == -1:
						nodes[i] = 0
						stack.append(i)
					elif nodes[i] == 1:
						return print('NO')
					graph[cur][i] = 0
					graph[i][cur] = 0
		else:
			for i in graph[cur]:
				if graph[cur][i]:
					if nodes[i] == -1:
						nodes[i] = 1
						stack.append(i)
					elif nodes[i] == 0:
						return print('NO')
					graph[cur][i] = 0
					graph[i][cur] = 0
	print('YES')
	out = ''
	for i in roads:
		if nodes[i[0]] == 1:
			out += '1'
		else:
			out += '0'
	return print(out)
main()


import math
from collections import deque

def main():
	(n, m) = map(int, input().split())
	g = [[] for _ in range(n)]
	edges = []
	for e in range(m):
		(a, b) = map(int, input().split())
		g[a - 1].append(b - 1)
		g[b - 1].append(a - 1)
		edges.append((a - 1, b - 1))
	used = [False] * n
	mark = [False] * n
	q = deque([])

	def bfs():
		node = 0
		used[node] = True
		mark[node] = True
		q.append(node)
		while q:
			node = q.popleft()
			for neigh in g[node]:
				if used[neigh]:
					if mark[neigh] == mark[node]:
						return False
				if not used[neigh]:
					used[neigh] = True
					mark[neigh] = not mark[node]
					q.append(neigh)
		return True
	res = bfs()
	if res:
		print('YES')
		print(''.join(map(lambda e: '1' if mark[e[0]] and (not mark[e[1]]) else '0', edges)))
	else:
		print('NO')
main()


from collections import defaultdict, deque

def bfs():
	q = deque([1])
	color[1] = 1
	while q:
		v = q.popleft()
		for i in g[v]:
			if color[i] == 0:
				color[i] = -color[v]
				q.append(i)
			elif color[i] == color[v]:
				return False
	return True
(n, m) = map(int, input().split())
edges = []
g = defaultdict(list)
for i in range(m):
	(u, v) = map(int, input().split())
	g[u].append(v)
	g[v].append(u)
	edges.append((u, v))
color = [0] * (n + 1)
r = bfs()
if r == False:
	print('NO')
	exit(0)
ans = []
for (u, v) in edges:
	if color[u] == 1 and color[v] == -1:
		ans.append('1')
	else:
		ans.append('0')
print('YES')
print(''.join(ans))


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')
import sys
import math
from math import gcd
import bisect
from collections import deque
(n, m) = map(int, input().split())
ed = []
g = [[] for i in range(n)]
for i in range(m):
	(u, v) = map(int, input().split())
	ed.append((u, v))
	g[u - 1].append(v - 1)
	g[v - 1].append(u - 1)
v = [-1] * n
q = deque([0])
v[0] = True
f = 0
while q:
	s = q.pop()
	for i in g[s]:
		if v[i] == -1:
			v[i] = not v[s]
			q.append(i)
		elif v[i] == v[s]:
			f = 1
if f == 1:
	print('NO')
else:
	print('YES')
	print(''.join(('1' if v[ed[i][0] - 1] else '0' for i in range(m))))


import math
from collections import deque, defaultdict
from sys import stdin, stdout
input = stdin.readline
listin = lambda : list(map(int, input().split()))
mapin = lambda : map(int, input().split())
(n, m) = map(int, input().split())
d = defaultdict(list)
edges = []
for _ in range(m):
	(u, v) = map(int, input().split())
	edges.append((u - 1, v - 1))
	d[u - 1].append(v - 1)
	d[v - 1].append(u - 1)
color = [-1] * n
color[0] = True
q = deque([0])
flag = True
while q:
	first = q.popleft()
	for i in d[first]:
		if color[i] == -1:
			q.append(i)
			color[i] = not color[first]
		elif color[first] == color[i]:
			flag = False
if flag:
	print('YES')
	print(''.join(('1' if color[edges[i][0]] else '0' for i in range(m))))
else:
	print('NO')


from collections import deque

def bpc(graph):
	q = deque()
	for u in range(len(graph)):
		if color[u] == -1:
			color[u] = 0
			q.append(u)
			while q:
				u = q.popleft()
				for v in graph[u]:
					if color[v] == -1:
						q.append(v)
						color[v] = 1 - color[u]
					elif color[v] == color[u]:
						return False
	return True
(n, m) = map(int, input().split())
graph = [[] for _ in range(n)]
color = [-1 for _ in range(n)]
xy = []
for i in range(m):
	pair = list(map(lambda x: int(x) - 1, input().split()))
	xy += [pair]
	graph[pair[0]].append(pair[1])
	graph[pair[1]].append(pair[0])
if not bpc(graph):
	print('NO')
else:
	print('YES')
	for i in range(m):
		if color[xy[i][0]] == 0:
			print(1, end='')
		else:
			print(0, end='')


from collections import deque

class Graph:

	def __init__(self, V):
		self.V = V
		self.adj_list = [[] for u in range(V + 1)]
		self.edges = []

	def add_edge(self, edge):
		self.edges.append(edge)

	def add_neighdor(self, v1, v2):
		self.adj_list[v1].append(v2)

	def get_neighdor(self, v):
		return self.adj_list[v]

def solve(graph):
	color = [0] * graph.V
	queue = [(0, 1)]
	color[0] = 1
	i = 0
	while i != len(queue):
		for v in graph.get_neighdor(queue[i][0]):
			if not color[v]:
				color[v] = 3 - queue[i][1]
				queue.append((v, color[v]))
		i += 1
	ans = ['0'] * len(graph.edges)
	for i in range(len(graph.edges)):
		if color[graph.edges[i][0]] == color[graph.edges[i][1]]:
			print('NO')
			return
		if color[graph.edges[i][0]] == 1:
			ans[i] = '1'
	print('YES')
	print(''.join(ans))

def get_input():
	(n, m) = map(int, input().split())
	graph = Graph(n)
	for _ in range(m):
		(v1, v2) = map(int, input().split())
		graph.add_neighdor(v1 - 1, v2 - 1)
		graph.add_neighdor(v2 - 1, v1 - 1)
		graph.add_edge((v1 - 1, v2 - 1))
	return graph
graph = get_input()
solve(graph)