You have a simple undirected graph consisting of n vertices and m edges. The graph doesn't contain self-loops, there is at most one edge between a pair of vertices. The given graph can be disconnected.

Let's make a definition.

Let v_1 and v_2 be two some nonempty subsets of vertices that do not intersect. Let f(v_{1}, v_{2}) be true if and only if all the conditions are satisfied:

  1. There are no edges with both endpoints in vertex set v_1. 
  2. There are no edges with both endpoints in vertex set v_2. 
  3. For every two vertices x and y such that x is in v_1 and y is in v_2, there is an edge between x and y. 



Create three vertex sets (v_{1}, v_{2}, v_{3}) which satisfy the conditions below;

  1. All vertex sets should not be empty. 
  2. Each vertex should be assigned to only one vertex set. 
  3. f(v_{1}, v_{2}), f(v_{2}, v_{3}), f(v_{3}, v_{1}) are all true. 



Is it possible to create such three vertex sets? If it's possible, print matching vertex set for each vertex.

Input

The first line contains two integers n and m (3 ≤ n ≤ 10^{5}, 0 ≤ m ≤ min(3 ⋅ 10^{5}, (n(n-1))/(2))) — the number of vertices and edges in the graph.

The i-th of the next m lines contains two integers a_{i} and b_{i} (1 ≤ a_{i} < b_{i} ≤ n) — it means there is an edge between a_{i} and b_{i}. The graph doesn't contain self-loops, there is at most one edge between a pair of vertices. The given graph can be disconnected.

Output

If the answer exists, print n integers. i-th integer means the vertex set number (from 1 to 3) of i-th vertex. Otherwise, print -1.

If there are multiple answers, print any.

Examples

Input


6 11
1 2
1 3
1 4
1 5
1 6
2 4
2 5
2 6
3 4
3 5
3 6


Output


1 2 2 3 3 3 

Input


4 6
1 2
1 3
1 4
2 3
2 4
3 4


Output


-1

Note

In the first example, if v_{1} = \{ 1 \}, v_{2} = \{ 2, 3 \}, and v_{3} = \{ 4, 5, 6 \} then vertex sets will satisfy all conditions. But you can assign vertices to vertex sets in a different way; Other answers like "2 3 3 1 1 1" will be accepted as well.

<image>

In the second example, it's impossible to make such vertex sets.
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main1 {
	static PrintWriter out = new PrintWriter(System.out, true);
	static FastReader input = new FastReader();
	final long MOD = (long) 1e9 + 7;
	int color[];
	boolean vis[];
	ArrayList<Integer> g[];
	ArrayList<Integer> dada[];
 
	void bfs(int nod, int c) {
 
		if (color[nod] != 0)
			return;
 
		Queue<Integer> q = new LinkedList<>();
		q.add(nod);
		vis[nod] = true;
		while (!q.isEmpty()) {
			int cur = q.poll();
 
			boolean can = true;
			for (int v : g[cur]) {
				if (color[v] == c) {
					can = false;
				}
 
				if (!vis[v]) {
					q.add(v);
					vis[v] = true;
				}
			}
			if (can) {
				color[cur] = c;
				dada[c].add(cur);
			}
		}
	}
 
	boolean check() {
 
		for (int v : dada[1]) {
			ArrayList<Integer> red = new ArrayList<>();
			ArrayList<Integer> blue = new ArrayList<>();
			for (int q : g[v]) {
				if (color[q] == 2) {
					red.add(q);
				} else if (color[q] == 3) {
					blue.add(q);
				}
			}
			if (red.size() != dada[2].size() || blue.size() != dada[3].size()) {
				return false;
			}
		}
		
		for (int v : dada[2]) {
			ArrayList<Integer> red = new ArrayList<>();
			ArrayList<Integer> blue = new ArrayList<>();
			for (int q : g[v]) {
				if (color[q] == 1) {
					red.add(q);
				} else if (color[q] == 3) {
					blue.add(q);
				}
			}
			if (red.size() != dada[1].size() || blue.size() != dada[3].size()) {
				return false;
			}
		}
		
		for (int v : dada[3]) {
			ArrayList<Integer> red = new ArrayList<>();
			ArrayList<Integer> blue = new ArrayList<>();
			for (int q : g[v]) {
				if (color[q] == 1) {
					red.add(q);
				} else if (color[q] == 2) {
					blue.add(q);
				}
			}
			if (red.size() != dada[1].size() || blue.size() != dada[2].size()) {
				return false;
			}
		}
		return true;
	}
 
	void main1() throws NumberFormatException, IOException {
 
		int n = input.nextInt();
		int m = input.nextInt();
		color = new int[n];
		vis = new boolean[n];
		g = allocateArrayList(n);
		dada = allocateArrayList(4);
		for (int i = 0; i < m; i++) {
			int x = input.nextInt() - 1;
			int y = input.nextInt() - 1;
			g[x].add(y);
			g[y].add(x);
		}
 
		for (int i = 0; i < n; i++) {
			if (!vis[i]) {
				bfs(i, 1);
			}
		}
		vis = new boolean[n];
		for (int i = 0; i < n; i++) {
			if (!vis[i]) {
				bfs(i, 2);
			}
		}
		vis = new boolean[n];
		for (int i = 0; i < n; i++) {
			if (!vis[i]) {
				bfs(i, 3);
			}
		}
		//out.println(Arrays.toString(color));
		if (dada[1].size() + dada[2].size() + dada[3].size() != n||dada[1].size()==0||dada[3].size()==0||dada[2].size()==0) {
			out.println(-1);
		} else {
			if (check()) {
				for (int i = 0 ; i < n ; i++) {
					out.print(color[i]+" ");
				}
			}
			else {
				out.println(-1);
			}
		}
		out.flush();
 
	}
 
	public static void main(String args[]) throws NumberFormatException, IOException {
		Main1 inst = new Main1();
		inst.main1();
	}
 
	static class FastReader {
		BufferedReader br;
		StringTokenizer st;
 
		public FastReader() {
			// try {
			// br = new BufferedReader(new FileReader(new File("overcode.in")));
			// } catch (FileNotFoundException e) {
			// e.printStackTrace();
			// }
			br = new BufferedReader(new InputStreamReader(System.in));
		}
 
		String next() throws IOException {
			while (st == null || !st.hasMoreElements()) { st = new StringTokenizer(br.readLine()); }
			return st.nextToken();
		}
 
		int nextInt() throws NumberFormatException, IOException { return Integer.parseInt(next()); }
 
		long nextLong() throws NumberFormatException, IOException { return Long.parseLong(next()); }
 
		double nextDouble() throws NumberFormatException, IOException { return Double.parseDouble(next()); }
 
		String nextLine() throws IOException {
			String str = "";
			str = br.readLine();
			return str;
		}
 
		boolean hasNext() throws IOException { return br.ready(); }
	}
 
	static class con {
		static int IINF = (int) 1e9;
		static int _IINF = (int) -1e9;
		static long LINF = (long) 1e15;
		static long _LINF = (long) -1e15;
		static double EPS = 1e-9;
	}
 
	static class Triple implements Comparable<Triple> {
		int x;
		int y;
 
		int z;
 
		Triple(int x, int y, int z) {
			this.x = x;
			this.y = y;
			this.z = z;
		}
 
		@Override
		public int compareTo(Triple o) {
			if (x == o.x && y == o.y)
				return z - o.z;
			if (x == o.x)
				return y - o.y;
			return x - o.x;
		}
 
		@Override
		public String toString() { return "(" + x + ", " + y + ", " + z + ")"; }
	}
 
	static class Pair implements Comparable<Pair> {
		int x;
		int y;
 
		Pair(int x, int y) {
			this.x = x;
			this.y = y;
 
		}
 
		@Override
		public int compareTo(Pair o) {
			if (x == o.x)
				return (int) (y - o.y);
			return (int) (x - o.x);
		}
 
		@Override
		public String toString() {
 
			return "(" + x + ", " + y + ")";
		}
 
	}
 
	static void shuffle(int[] a) {
		for (int i = 0; i < a.length; i++) {
			int r = i + (int) (Math.random() * (a.length - i));
			int tmp = a[r];
			a[r] = a[i];
			a[i] = tmp;
		}
	}
 
	static void shuffle(long[] a) {
		for (int i = 0; i < a.length; i++) {
			int r = i + (int) (Math.random() * (a.length - i));
			long tmp = a[r];
			a[r] = a[i];
			a[i] = tmp;
		}
	}
 
	static int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
 
	static long gcd(long a, long b) { return b == 0 ? a : gcd(b, a % b); }
 
	static class DSU {
 
		int[] p, rank, setSize;
		int numSets;
 
		DSU(int n) {
			p = new int[n];
			rank = new int[n];
			setSize = new int[n];
			numSets = n;
 
			for (int i = 0; i < n; i++) {
				p[i] = i;
				setSize[i] = 1;
			}
 
		}
 
		int findSet(int n) { return p[n] = p[n] == n ? n : findSet(p[n]); }
 
		boolean isSameSet(int n, int m) { return findSet(n) == findSet(m); }
 
		void mergeSet(int n, int m) {
 
			if (!isSameSet(n, m)) {
				numSets--;
				int p1 = findSet(n);
				int p2 = findSet(m);
 
				if (rank[p1] > rank[p2]) {
					p[p2] = p1;
					setSize[p1] += setSize[p2];
				} else {
					p[p1] = p2;
					setSize[p2] += setSize[p1];
					if (rank[p1] == rank[p2])
						rank[p1]++;
				}
			}
 
		}
 
		int size() { return numSets; }
 
		int setSize(int n) { return setSize[findSet(n)]; }
 
	}
 
	static class Reader {
		final private int BUFFER_SIZE = 1 << 16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer, bytesRead;
 
		public Reader() {
			din = new DataInputStream(System.in);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
 
		public Reader(String file_name) throws IOException {
			din = new DataInputStream(new FileInputStream(file_name));
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}
 
		public String readLine() throws IOException {
			byte[] buf = new byte[1024];
			int cnt = 0, c;
			while ((c = read()) != -1) {
				if (c == '\n')
					break;
				buf[cnt++] = (byte) c;
			}
			return new String(buf, 0, cnt);
		}
 
		public int nextInt() throws IOException {
			int ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do { ret = ret * 10 + c - '0'; } while ((c = read()) >= '0' && c <= '9');
			if (neg)
				return -ret;
			return ret;
		}
 
		public long nextLong() throws IOException {
			long ret = 0;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do { ret = ret * 10 + c - '0'; } while ((c = read()) >= '0' && c <= '9');
			if (neg)
				return -ret;
			return ret;
		}
 
		// ddd
		public double nextDouble() throws IOException {
			double ret = 0, div = 1;
			byte c = read();
			while (c <= ' ')
				c = read();
			boolean neg = (c == '-');
			if (neg)
				c = read();
			do { ret = ret * 10 + c - '0'; } while ((c = read()) >= '0' && c <= '9');
			if (c == '.')
				while ((c = read()) >= '0' && c <= '9')
					ret += (c - '0') / (div *= 10);
			if (neg)
				return -ret;
			return ret;
		}
 
		private void fillBuffer() throws IOException {
			bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
			if (bytesRead == -1)
				buffer[0] = -1;
		}
 
		private byte read() throws IOException {
			if (bufferPointer == bytesRead)
				fillBuffer();
			return buffer[bufferPointer++];
		}
 
		public void close() throws IOException {
			if (din == null)
				return;
			din.close();
		}
	}
 
	static ArrayList<Integer>[] allocateArrayList(int n) {
		ArrayList<Integer> g[] = new ArrayList[n];
		for (int i = 0; i < n; i++) { g[i] = new ArrayList<>(); }
		return g;
	}
}