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.
#include <bits/stdc++.h>
using namespace std;
int n, m;
string ans[100100];
int from[100100];
int to[100100];
int weight[100100];
vector<pair<int, int> > G[100100];
vector<pair<int, int> > edg;
set<pair<int, int> > alreadyConnected;
set<pair<int, int> > sameComp;
set<int> nodes;
vector<int> fooE;
int rnk[100100];
int par[100100];
int vis[100100];
int dfsLow[100100];
int dfsNum[100100];
int dfsParent[100100];
int TIMER = 1;
void init() {
  for (int i = 0; i <= n; i++) par[i] = i, rnk[i] = 0;
}
int findSet(int u) {
  if (par[u] == u) return u;
  return par[u] = findSet(par[u]);
}
int isSame(int u, int v) { return (findSet(u) == findSet(v)); }
void merge(int u, int v) {
  int x = findSet(u), y = findSet(v);
  if (isSame(u, v)) return;
  if (rnk[x] < rnk[y])
    par[x] = y;
  else {
    par[y] = x;
    if (rnk[x] == rnk[y]) rnk[x]++;
  }
}
void dfs(int u) {
  vis[u] = 1;
  dfsLow[u] = dfsNum[u] = TIMER++;
  for (int i = 0; i < G[u].size(); i++) {
    int nxt = G[u][i].first, id = G[u][i].second;
    if (dfsNum[nxt] == -1) {
      dfsParent[nxt] = u;
      dfs(nxt);
      if (dfsLow[nxt] > dfsNum[u]) ans[id] = "any";
      dfsLow[u] = min(dfsLow[u], dfsLow[nxt]);
    } else if (nxt != dfsParent[u])
      dfsLow[u] = min(dfsLow[u], dfsNum[nxt]);
  }
}
void handleEdges() {
  nodes.clear();
  alreadyConnected.clear();
  sameComp.clear();
  for (int i = 0; i < fooE.size(); i++) {
    int id = fooE[i];
    nodes.insert(findSet(from[id]));
    nodes.insert(findSet(to[id]));
    if (isSame(from[id], to[id])) {
      ans[id] = "none";
      continue;
    }
  }
  int haCnt = 0;
  for (int i = 0; i < fooE.size(); i++) {
    int id = fooE[i];
    if (isSame(from[id], to[id])) continue;
    int fromComp = findSet(from[id]), toComp = findSet(to[id]);
    if (alreadyConnected.count(make_pair(fromComp, toComp))) {
      sameComp.insert(make_pair(fromComp, toComp));
      sameComp.insert(make_pair(toComp, fromComp));
    }
    alreadyConnected.insert(make_pair(fromComp, toComp));
    alreadyConnected.insert(make_pair(toComp, fromComp));
    G[fromComp].push_back(make_pair(toComp, id));
    G[toComp].push_back(make_pair(fromComp, id));
    vis[fromComp] = vis[toComp] = 0;
    dfsLow[fromComp] = dfsLow[toComp] = 0;
    dfsParent[fromComp] = dfsParent[toComp] = 0;
    dfsNum[fromComp] = dfsNum[toComp] = -1;
  }
  for (set<int>::iterator it = nodes.begin(); it != nodes.end(); it++) {
    int id = findSet(*it);
    if (vis[id]) continue;
    dfs(id);
  }
  for (int i = 0; i < fooE.size(); i++) {
    int id = fooE[i];
    int fromComp = findSet(from[id]), toComp = findSet(to[id]);
    if (sameComp.count(make_pair(fromComp, toComp))) ans[id] = "at least one";
    G[fromComp].clear();
    G[toComp].clear();
  }
  for (int i = 0; i < fooE.size(); i++) {
    int id = fooE[i];
    int fromComp = findSet(from[id]), toComp = findSet(to[id]);
    merge(fromComp, toComp);
  }
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    cin >> from[i] >> to[i] >> weight[i];
    ans[i] = "at least one";
    edg.push_back(make_pair(weight[i], i));
  }
  init();
  sort(edg.begin(), edg.end());
  for (int i = 0; i < m; i++) {
    fooE.push_back(edg[i].second);
    if (i + 1 < m && edg[i].first == edg[i + 1].first) continue;
    handleEdges();
    fooE.clear();
  }
  for (int i = 0; i < m; i++) cout << ans[i] << endl;
  return 0;
}
