You are given a directed graph with $n$ vertices and $m$ directed edges without self-loops or multiple edges.

Let's denote the $k$-coloring of a digraph as following: you color each edge in one of $k$ colors. The $k$-coloring is good if and only if there no cycle formed by edges of same color.

Find a good $k$-coloring of given digraph with minimum possible $k$.


-----Input-----

The first line contains two integers $n$ and $m$ ($2 \le n \le 5000$, $1 \le m \le 5000$) — the number of vertices and edges in the digraph, respectively.

Next $m$ lines contain description of edges — one per line. Each edge is a pair of integers $u$ and $v$ ($1 \le u, v \le n$, $u \ne v$) — there is directed edge from $u$ to $v$ in the graph.

It is guaranteed that each ordered pair $(u, v)$ appears in the list of edges at most once.


-----Output-----

In the first line print single integer $k$ — the number of used colors in a good $k$-coloring of given graph.

In the second line print $m$ integers $c_1, c_2, \dots, c_m$ ($1 \le c_i \le k$), where $c_i$ is a color of the $i$-th edge (in order as they are given in the input).

If there are multiple answers print any of them (you still have to minimize $k$).


-----Examples-----
Input
4 5
1 2
1 3
3 4
2 4
1 4

Output
1
1 1 1 1 1 

Input
3 3
1 2
2 3
3 1

Output
2
1 1 2

Difficulty: HARD

Solutions:
(n, m) = input().split()
n = int(n)
m = int(m)
ady = [[] for _ in range(n + 1)]
color = [0] * (n + 1)
oneColor = True
sol = [0] * m

def dfs_visit(v):
	global sol, ady, oneColor, color
	color[v] = 1
	for par in ady[v]:
		(u, index) = (par[0], par[1])
		if color[u] == 0:
			dfs_visit(u)
			sol[index] = 1
		elif color[u] == 2:
			sol[index] = 1
		else:
			sol[index] = 2
			oneColor = False
	color[v] = 2
for i in range(m):
	(n1, n2) = input().split()
	n1 = int(n1)
	n2 = int(n2)
	ady[n1].append((n2, i))
for v in range(1, n + 1):
	if color[v] == 0:
		dfs_visit(v)
if oneColor:
	print(1)
else:
	print(2)
res = str('')
for i in range(0, m):
	res += str(sol[i]) + str(' ')
print(res)


(n, m) = input().split()
n = int(n)
m = int(m)
ady = [[] for _ in range(n + 1)]
low = [0] * (n + 1)
vdfs = [0] * (n + 1)
ndfs = int(0)
oneColor = True
mark = [False] * (n + 1)
sol = [0] * m

def dfs(nod):
	global sol, ndfs, ady, vdfs, low, oneColor, ant, pila
	ndfs += 1
	vdfs[nod] = low[nod] = ndfs
	for par in ady[nod]:
		to = par[0]
		index = par[1]
		sol[index] = 1
		if vdfs[to] == 0:
			dfs(to)
			low[nod] = min(low[to], low[nod])
		elif mark[to] == False:
			low[nod] = min(low[nod], vdfs[to])
			if low[to] <= vdfs[nod]:
				oneColor = False
				sol[index] = 2
	mark[nod] = True
for i in range(m):
	(n1, n2) = input().split()
	n1 = int(n1)
	n2 = int(n2)
	ady[n1].append((n2, i))
for i in range(1, n + 1):
	if vdfs[i] == 0:
		dfs(i)
if oneColor:
	print(1)
else:
	print(2)
res = str('')
for i in range(0, m):
	res += str(sol[i]) + str(' ')
print(res)


from collections import deque

def DFS(x, color, solucion):
	color[x] = 1
	c = False
	for (y, i) in adyacentes[x]:
		if color[y] == 0:
			c = DFS(y, color, solucion) or c
			solucion[i] = 1
		elif color[y] == 2:
			solucion[i] = 1
		else:
			solucion[i] = 2
			c = True
	color[x] = 2
	return c

def Solucion():
	color = [0] * n
	solucion = [0] * m
	c = False
	for l in range(0, n):
		if color[l] == 0:
			c = DFS(l, color, solucion) or c
	print(2 if c else 1)
	print(*solucion, sep=' ')
(n, m) = map(int, input().split())
adyacentes = [[] for _ in range(0, n)]
for i in range(0, m):
	(u, v) = map(lambda x: int(x) - 1, input().split())
	adyacentes[u].append((v, i))
Solucion()


import os
import sys
from collections import defaultdict

def get_adj(edges):
	neighbors = defaultdict(list, {})
	for (v1, v2) in edges:
		neighbors[v1].append(v2)
	return dict(neighbors)
NEW = 0
VISITING = 1
CLOSED = 2

def solve(edges, n):
	adj = get_adj(edges)
	status = [NEW] * (n + 1)
	edge_idx = {tuple(e): idx for (idx, e) in enumerate(edges)}
	colors = [1] * len(edges)
	has_loop = [False]

	def dfs(root):
		if status[root] == CLOSED:
			return
		status[root] = VISITING
		children = adj.get(root, [])
		for c in children:
			if status[c] == NEW:
				dfs(c)
			elif status[c] == VISITING:
				colors[edge_idx[root, c]] = 2
				has_loop[0] = True
			elif status[c] == CLOSED:
				pass
		status[root] = CLOSED
	for i in range(1, n + 1):
		dfs(i)
	return (has_loop[0], colors)

def pp(input):
	(n, m) = map(int, input().strip().split())
	edges = [tuple(map(int, input().strip().split())) for _ in range(m)]
	(has_loop, colors) = solve(edges, n)
	print(int(has_loop) + 1)
	print(' '.join(map(str, colors)))
if 'pydev' in sys.argv[0]:
	from string_source import string_source, codeforces_parse
	x = 'inputCopy\n4 5\n1 2\n1 3\n3 4\n2 4\n1 4\noutputCopy\n1\n1 1 1 1 1 \ninputCopy\n3 3\n1 2\n2 3\n3 1\noutputCopy\n2\n1 1 2 '
	for (q, a) in codeforces_parse(x):
		pp(string_source(q))
		print(a)
		print('----')
else:
	pp(sys.stdin.readline)


from collections import defaultdict
vis = []

def isCyclic(n, graph):
	global vis
	global k
	vis = [0] * n
	rec = [0] * n
	for i in range(0, n):
		if vis[i] == False:
			if DfsRec(i, rec, graph):
				j = 0
	return False

def DfsRec(i, rec, g):
	global s1
	global s2
	global vis
	global k
	vis[i] = True
	rec[i] = True
	for u in g[i]:
		if vis[u] == False:
			DfsRec(u, rec, g)
		elif rec[u] == True:
			k = 1
			colors[i, u] = 2
			s1 = i
			s2 = u
	rec[i] = False
	return False
(n, e) = list(map(int, input().split()))
d = defaultdict(lambda : [])
colors = defaultdict(lambda : 1)
l = []
for i in range(0, e):
	(a, b) = list(map(int, input().split()))
	l.append([a - 1, b - 1])
	d[a - 1].append(b - 1)
s1 = -1
s2 = -1
k = 0
c = isCyclic(n, d)
if k == 1:
	print(2)
	ans = []
	for (i, j) in l:
		ans.append(colors[i, j])
	print(*ans)
else:
	print(1)
	l = [1] * e
	print(*l)


def DFS(x, color, adyacentes, solucion):
	color[x] = 1
	c = False
	for (y, i) in adyacentes[x]:
		if color[y] == 0:
			c = DFS(y, color, adyacentes, solucion) or c
		elif color[y] == 1:
			solucion[i] = 2
			c = True
	color[x] = 2
	return c

def ColoringEdges():
	(n, m) = map(int, input().split())
	adyacentes = [[] for _ in range(0, n)]
	for i in range(0, m):
		(u, v) = map(lambda x: int(x) - 1, input().split())
		adyacentes[u].append((v, i))
	color = [0] * n
	solucion = [1] * m
	c = False
	for r in range(0, n):
		if color[r] == 0:
			c = DFS(r, color, adyacentes, solucion) or c
	print(2 if c else 1)
	print(*solucion, sep=' ')
ColoringEdges()