You are given a connected weighted undirected graph without any loops and multiple edges. 

Let us remind you that a graph's spanning tree is defined as an acyclic connected subgraph of the given graph that includes all of the graph's vertexes. The weight of a tree is defined as the sum of weights of the edges that the given tree contains. The minimum spanning tree (MST) of a graph is defined as the graph's spanning tree having the minimum possible weight. For any connected graph obviously exists the minimum spanning tree, but in the general case, a graph's minimum spanning tree is not unique.

Your task is to determine the following for each edge of the given graph: whether it is either included in any MST, or included at least in one MST, or not included in any MST.

Input

The first line contains two integers n and m (2 ≤ n ≤ 105, <image>) — the number of the graph's vertexes and edges, correspondingly. Then follow m lines, each of them contains three integers — the description of the graph's edges as "ai bi wi" (1 ≤ ai, bi ≤ n, 1 ≤ wi ≤ 106, ai ≠ bi), where ai and bi are the numbers of vertexes connected by the i-th edge, wi is the edge's weight. It is guaranteed that the graph is connected and doesn't contain loops or multiple edges.

Output

Print m lines — the answers for all edges. If the i-th edge is included in any MST, print "any"; if the i-th edge is included at least in one MST, print "at least one"; if the i-th edge isn't included in any MST, print "none". Print the answers for the edges in the order in which the edges are specified in the input.

Examples

Input

4 5
1 2 101
1 3 100
2 3 2
2 4 2
3 4 1


Output

none
any
at least one
at least one
any


Input

3 3
1 2 1
2 3 1
1 3 2


Output

any
any
none


Input

3 3
1 2 1
2 3 1
1 3 1


Output

at least one
at least one
at least one

Note

In the second sample the MST is unique for the given graph: it contains two first edges.

In the third sample any two edges form the MST for the given graph. That means that each edge is included at least in one MST.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.StringTokenizer;


public class EdgesinMST {


	static int col[] = new int[100000+5];
	static String[] query = {"none","at least one","any"};
	static ArrayList<Edge> edges = new ArrayList();
	static IR in  = new IR(System.in);
	static int N,E;
	static int dfsnum[] = new int[100000+5];
	static int dfslow[] = new int[100000+5];
	static ArrayList<Edge> graph[] = new ArrayList[100000+5];
	static int counter = 0;
	static DSU dsu;
	public static void dfs(int idx,int p)
	{
		dfsnum[idx] = dfslow[idx] = counter++;

		for(Edge e : graph[idx])
		{
			//System.err.println(e.u+" "+e.v);
			int k = e.v;
			if(dfsnum[k] == -1)
			{
				dfs(k,e.id);

				if(dfsnum[idx] < dfslow[k])
				{
					//dsu.union(e.u,e.v);
					
					col[e.id] = 2;

				}
				dfslow[idx] = Math.min(dfslow[idx],dfslow[k]);
			}
			else
			{
				if(e.id != p) dfslow[idx] = Math.min(dfslow[idx],dfsnum[k]);
			}

		}

	}


	static class Edge implements Comparable<Edge>
	{
		int u,v,cost,id;
		int oldid;

		public Edge(int u,int v,int cost)
		{
			this.u = u;
			this.v = v;
			this.cost = cost;

		}
		public Edge(int u,int v,int cost,int id)
		{
			this.u = u;
			this.v = v;
			this.cost = cost;
			this.id = id;

		}



		public int compareTo(Edge o) {
			return this.cost - o.cost;
		}
	}

	public static void main(String[]args)throws Throwable
	{
		N = in.j(); E = in.j();

		for(int e = 0 ; e < E ; e++)
		{
			edges.add(new Edge(in.j() - 1,in.j() - 1,in.j()));

			Edge p = edges.get(e);
			p.oldid = e;
		}
		for(int i = 0 ; i < N ; i++) graph[i] = new ArrayList();

		dsu = new DSU(N);
		Collections.sort(edges);
		for(int i = 0 ; i < edges.size() ; i++)
		{
			Edge e = edges.get(i);
			e.id = i;
		}
		Arrays.fill(dfsnum,-1);
		Arrays.fill(dfslow,-1);
		String ans[] = new String[E];
		StringBuilder res = new StringBuilder();

		ArrayList<Integer> nodes = new ArrayList();
		for(int i = 0 ; i < edges.size() ; i++)
		{
			Edge e = edges.get(i);
			int u = e.u;
			int v = e.v;
			if(dsu.isSameSet(u, v))
			{
				col[e.id] = 0;
			}
			else
			{
				col[e.id] = 1;
				int nextid = i + 1;
				boolean in = false;

				counter = 0;
				nodes.clear();
				while(nextid < edges.size() && edges.get(nextid).cost == e.cost)
				{
					if(!dsu.isSameSet(edges.get(nextid).u, edges.get(nextid).v))
					{
						Edge p = edges.get(nextid);
						in = true;
						col[nextid] = 1;
						graph[dsu.getParent(p.u)].add(new Edge(dsu.getParent(p.u),dsu.getParent(p.v),p.cost,p.id));
						graph[dsu.getParent(p.v)].add(new Edge(dsu.getParent(p.v),dsu.getParent(p.u),p.cost,p.id));
						dfsnum[dsu.getParent(p.u)] = -1;
						dfsnum[dsu.getParent(p.v)] = -1;
						dfslow[dsu.getParent(p.v)] = -1;
						dfslow[dsu.getParent(p.u)] = -1;
						nodes.add(dsu.getParent(p.u));
						nodes.add(dsu.getParent(p.v));
					}
					else
					{
						col[nextid] = 0;

					}
					++nextid;
				}
				if(in)
				{
					nodes.add(dsu.getParent(e.u));
					nodes.add(dsu.getParent(e.v));
					graph[dsu.getParent(e.u)].add(new Edge(dsu.getParent(e.u),dsu.getParent(e.v),e.cost,e.id));
					graph[dsu.getParent(e.v)].add(new Edge(dsu.getParent(e.v),dsu.getParent(e.u),e.cost,e.id));
					for(Integer a : nodes) if(dfsnum[a] == -1) dfs(a,-1);

				}
				else col[e.id] = 2;

				for(int j = i ; j < nextid ; j++)
				{
					graph[dsu.getParent(edges.get(j).u)].clear();
					graph[dsu.getParent(edges.get(j).v)].clear();
					dfsnum[dsu.getParent(edges.get(j).u)] = -1;
					dfsnum[dsu.getParent(edges.get(j).v)] = -1;
					dfslow[dsu.getParent(edges.get(j).v)] = -1;
					dfslow[dsu.getParent(edges.get(j).u)] = -1;
				}
				for(int j = i ; j < nextid ;j++)
				{
					dsu.union(edges.get(j).u, edges.get(j).v);
				}
				i = nextid - 1;
			}

		}
		for(Edge e : edges)
		{
			ans[e.oldid] = query[col[e.id]];
		}
		for(int i = 0 ; i < E ; i++) res.append(ans[i]+"\n");
		System.out.print(res);


	}



	static	class IR {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

		public IR(InputStream stream) {
			reader = new BufferedReader(new InputStreamReader(stream), 32768);
			tokenizer = null;
		}

		public String next() {
			while (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					tokenizer = new StringTokenizer(reader.readLine());
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
			return tokenizer.nextToken();
		}

		public int j() {
			return Integer.parseInt(next());
		}
		public long ll(){
			return Long.parseLong(next());
		}


	}










	static class DSU {
		int rank[];
		int parent[];
		int N;
		int sets;
		int setsize[];

		public DSU(int N){
			this.N = N;
			sets = N;
			parent = new int[N];
			rank = new int[N];
			setsize = new int[N];
			for(int i=0;i<N;i++){ parent[i] = i; setsize[i] = 1; }

		}

		public void union(int x,int y){
			if(isSameSet(x,y)) return;
			sets--;
			int xp = getParent(x);
			int yp = getParent(y);
			if(rank[xp]>rank[yp]){ parent[yp] = xp; setsize[xp]+=setsize[yp];}
			else{
				if(rank[xp]==rank[yp]){
					rank[yp]++;
					parent[xp] = yp;
					setsize[yp]+=setsize[xp];
				}
				else
				{ parent[xp] =yp; setsize[yp] += setsize[xp]; }
			}

		}

		public int getParent(int x){
			if(x==parent[x]) return x;
			return parent[x] = getParent(parent[x]);
		}

		public boolean isSameSet(int x,int y){
			return getParent(x)==getParent(y);
		}

		public int numDisjointSets(){
			return sets;
		}
		public int getSetSize(int x){
			return setsize[getParent(x)];
		}



	}
}
