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 ≤ n ≤ 5000, 1 ≤ m ≤ 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 ≤ u, v ≤ n, u ≠ 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, ..., c_m (1 ≤ c_i ≤ 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 
import java.util.*;
import java.io.*;

public class Main {
	public static void main(String args[]) {new Main().run();}

	FastReader in = new FastReader();
	PrintWriter out = new PrintWriter(System.out);
	void run(){
		work();
		out.flush();
	}
	long mod=998244353L;
	ArrayList<int[]>[] graph;
	int[] visited;
	int[] color;
	int ret=1;
	void work() {
		int n=in.nextInt();
		int m=in.nextInt();
		graph=(ArrayList<int[]>[])new ArrayList[n+1];//index
		visited=new int[n+1];
		color=new int[m+1];
		Arrays.fill(color, 1);
		for(int i=1;i<=n;i++) {
			graph[i]=new ArrayList<>();
		}
		for(int i=1;i<=m;i++) {
			int n1=in.nextInt();
			int n2=in.nextInt();
			graph[n1].add(new int[] {n2,i});
		}
		for(int i=1;i<=n;i++) {
			if(visited[i]==0) {
				dfs(i);
			}
		}
		out.println(ret);
		for(int i=1;i<=m;i++) {
			out.print(color[i]+" ");
		}
	}
	private void dfs(int node) {
		visited[node]=1;
		for(int[] next:graph[node]) {
			int nn=next[0];
			int index=next[1];
			if(visited[nn]==1) {
				color[index]=2;
				ret=2;
			}else if(visited[nn]==0){
				dfs(nn);
			}
		}
		visited[node]=2;
	}
}



class FastReader
{
	BufferedReader br;
	StringTokenizer st;

	public FastReader()
	{
		br=new BufferedReader(new InputStreamReader(System.in));
	}

	public String next() 
	{
		if(st==null || !st.hasMoreElements())
		{
			try {
				st = new StringTokenizer(br.readLine());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return st.nextToken();
	}

	public int nextInt() 
	{
		return Integer.parseInt(next());
	}

	public long nextLong()
	{
		return Long.parseLong(next());
	}
}