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.*;
import java.util.*;
 
 
 
public class Main {
	
	static InputReader in = new InputReader(System.in);
	static PrintWriter out = new PrintWriter(System.out);
	
	static int oo = (int)1e9;
	static int mod = 1_000_000_007;
	
	static int[] di = {-1, 1, 0, 0};
	static int[] dj = {0, 0, -1, 1};

	
	public static void main(String[] args) throws IOException {

		int n = in.nextInt();
		int m = in.nextInt();
		HashSet<Integer>[] adj = new HashSet[n];
		for(int i = 0; i < n; ++i)
			adj[i] = new HashSet<>();
		for(int i = 0; i < m; ++i) {
			int u = in.nextInt() - 1;
			int v = in.nextInt() - 1;
			adj[u].add(v);
			adj[v].add(u);
		}
		int[] set = new int[n];
		int num = 0;
		for(int i = 0; i < n; ++i) {
			if(set[i] == 0) {
				num++;
				if(num >= 4) {
					break;
				}
				for(int j = 0; j < n; ++j) {
					if(!adj[i].contains(j)) {
						if(set[j] != 0) {
							System.out.println(-1);
							return;
						}
						set[j] = num;
					}
				}
			}
		}
		if(num != 3) {
			System.out.println(-1);
			return;
		}
		
		for(int i = 0; i < n; ++i) {
			for(int j : adj[i]) {
				if(set[i] == set[j]) {
					System.out.println(-1);
					return;
				}
			}
		}
		
		int[] cnt = new int[4];
		for(int i = 0; i < n; ++i) {
			cnt[set[i]]++;
		}

		for(int i = 0; i < n; ++i) {
			if(adj[i].size() != n - cnt[set[i]]) {
				System.out.println(-1);
				return;
			}
		}
		
		
		for(int x : set)
			out.print(x + " ");
		
		
		out.close();
	}
	
	
	static class SegmentTree {
		int n;
		long[] a, seg;
		int DEFAULT_VALUE = 0;
		
		public SegmentTree(long[] a, int n) {
			super();
			this.a = a;
			this.n = n;
			seg = new long[n * 4 + 1];
			build(1, 0, n-1);
		}
		
		private long build(int node, int i, int j) {
			if(i == j)
				return seg[node] = a[i];
			long first = build(node * 2, i, (i+j) / 2);
			long second = build(node * 2 + 1, (i+j) / 2 + 1, j);
			return seg[node] = combine(first, second);
		}
		
		long update(int k, long value) {
			return update(1, 0, n-1, k, value);
		}
		
		private long update(int node, int i, int j, int k, long value) {
			if(k < i || k > j)
				return seg[node];
			if(i == j && j == k) {
				a[k] = value;
				seg[node] = value;
				return value;
			}
			
			int m = (i + j) / 2;
			long first = update(node * 2, i, m, k, value);
			long second = update(node * 2 + 1, m + 1, j, k, value);
			return seg[node] = combine(first, second);
		}
		
		long query(int l, int r) {
			return query(1, 0, n-1, l, r);
		}
		
		private long query(int node, int i, int j, int l, int r) {
			if(l <= i && j <= r)
				return seg[node];
			if(j < l || i > r)
				return DEFAULT_VALUE;
			int m = (i + j) / 2;
			long first = query(node * 2, i, m, l, r);
			long second = query(node * 2 + 1, m+1, j, l, r);
			return combine(first, second);
		}
 
		private long combine(long a, long b) {
			return a + b;
		}
	}
	
	static class DisjointSet {
		int n;
		int[] g;
		int[] h;
		public DisjointSet(int n) {
			super();
			this.n = n;
			g = new int[n];
			h = new int[n];
			for(int i = 0; i < n; ++i) {
				g[i] = i;
				h[i] = 1;
			}
		}
		int find(int x) {
			if(g[x] == x)
				return x;
			return g[x] = find(g[x]);
		}
		void union(int x, int y) {
			x = find(x); y = find(y);
			if(x == y)
				return;
			if(h[x] >= h[y]) {
				g[y] = x;
				if(h[x] == h[y])
					h[x]++;
			}
			else {
				g[x] = y;
			}
		}
	}
	
	
	static int[] getPi(char[] a) {
		int m = a.length;
		int j = 0;
		int[] pi = new int[m];
		for(int i = 1; i < m; ++i) {
			while(j > 0 && a[i] != a[j])
				j = pi[j-1];
			if(a[i] == a[j]) {
				pi[i] = j + 1;
				j++;
			}
		}
		return pi;
	}
	
	static long lcm(long a, long b) {
		return a * b / gcd(a, b);
	}
	
	static boolean nextPermutation(int[] a) {
		for(int i = a.length - 2; i >= 0; --i) {
			if(a[i] < a[i+1]) {
				for(int j = a.length - 1; ; --j) {
					if(a[i] < a[j]) {
						int t = a[i];
						a[i] = a[j];
						a[j] = t;
						for(i++, j = a.length - 1; i < j; ++i, --j) {
							t = a[i];
							a[i] = a[j];
							a[j] = t;
						}
						return true;
					}
				}
			}
		}
		return false;
	}
	
	
	static void shuffle(int[] a) {
		Random r = new Random();
		for(int i = a.length - 1; i > 0; --i) {
			int si = r.nextInt(i);
			int t = a[si];
			a[si] = a[i];
			a[i] = t;
		}
	}
	
	static void shuffle(long[] a) {
		Random r = new Random();
		for(int i = a.length - 1; i > 0; --i) {
			int si = r.nextInt(i);
			long t = a[si];
			a[si] = a[i];
			a[i] = t;
		}
	}
	
	static int lower_bound(int[] a, int n, int k) {
		int s = 0;
		int e = n;
		int m;
		while (e - s > 0) {
			m = (s + e) / 2;
			if (a[m] < k)
				s = m + 1;
			else
				e = m;
		}
		return e;
	}
	static int lower_bound(long[] a, int n, long k) {
		int s = 0;
		int e = n;
		int m;
		while (e - s > 0) {
			m = (s + e) / 2;
			if (a[m] < k)
				s = m + 1;
			else
				e = m;
		}
		return e;
	}
	
	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 Pair implements Comparable<Pair> {
		int first, second;
 
		public Pair(int first, int second) {
			super();
			this.first = first;
			this.second = second;
		}
 
		@Override
		public int compareTo(Pair o) {
			return this.first != o.first ? this.first - o.first : this.second - o.second;
		}
		
//		@Override
//		public int compareTo(Pair o) {
//			return this.first != o.first ? o.first - this.first : o.second - this.second;
//		}
 
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + first;
			result = prime * result + second;
			return result;
		}
 
		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Pair other = (Pair) obj;
			if (first != other.first)
				return false;
			if (second != other.second)
				return false;
			return true;
		}
	}
}
 
 
 
class InputReader {
 
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;
 
	public InputReader(InputStream st) {
		this.stream = st;
	}
 
	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}
 
	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}
 
	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}
 
	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}
 
	public String readString() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isSpaceChar(c));
		return res.toString();
	}
 
	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}
 
	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}
 
	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
 
}