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 par[100005][20];
int ans[100005][20];
int ans1[100005][20];
int depth[100005];
vector<pair<int, int>> g[100005];
int n, m;
int parent[100005];
long long tot;
int GorB[100005];
int Fians[100005];
struct node {
  int x, y, w, id;
  node(int x, int y, int w, int id) {
    this->x = x;
    this->y = y;
    this->w = w;
    this->id = id;
  }
  bool operator<(const node& other) const {
    return w < other.w;
    return false;
  }
};
vector<node> tem;
int find_par(int u) {
  return parent[u] = ((parent[u] == u) ? u : find_par(parent[u]));
}
void kruskal() {
  for (int i = 1; i <= n; i++) parent[i] = i;
  sort(tem.begin(), tem.end());
  int cnt = 0;
  for (int i = 0; i < m; i++) {
    int u = tem[i].x;
    int v = tem[i].y;
    int w = tem[i].w;
    int id = tem[i].id;
    if (find_par(u) != find_par(v)) {
      parent[find_par(u)] = find_par(v);
      cnt++;
      g[u].push_back({v, w});
      g[v].push_back({u, w});
      GorB[id] = 2;
      tot += w;
      if (cnt == n - 1) break;
    }
  }
}
void dfs(int u, int p, int lvl) {
  par[u][0] = p;
  depth[u] = lvl;
  for (auto it : g[u]) {
    int v = it.first;
    int w = it.second;
    if (v == p) continue;
    ans[v][0] = w;
    ans1[v][0] = w;
    dfs(v, u, lvl + 1);
  }
}
void init(int root) {
  dfs(root, -1, 1);
  for (int j = 1; j < 20; j++) {
    for (int i = 1; i <= n; i++) {
      if (par[i][j - 1] != -1) {
        par[i][j] = par[par[i][j - 1]][j - 1];
        ans[i][j] = max(ans[i][j - 1], ans[par[i][j - 1]][j - 1]);
        ans1[i][j] = ans[i][j];
      } else
        par[i][j] = -1;
    }
  }
}
int query(int u, int v) {
  if (u == v) return 0;
  if (depth[u] < depth[v]) swap(u, v);
  int diff = depth[u] - depth[v];
  int re = 0;
  for (int i = 20 - 1; i >= 0; i--) {
    if (diff >= (1 << i)) {
      diff -= (1 << i);
      re = max(re, ans[u][i]);
      u = par[u][i];
    }
  }
  if (u == v) return re;
  for (int i = 20 - 1; i >= 0; i--) {
    if (par[u][i] != par[v][i]) {
      re = max({re, ans[u][i], ans[v][i]});
      u = par[u][i];
      v = par[v][i];
    }
  }
  re = max({re, ans[u][0], ans[v][0]});
  return re;
}
int lca(int u, int v) {
  if (depth[u] < depth[v]) swap(u, v);
  int log = 1;
  while (1) {
    int next = log + 1;
    if (depth[u] < (1 << next)) break;
    log++;
  }
  for (int i = log; i >= 0; i--) {
    if (depth[u] - (1 << i) >= depth[v]) {
      u = par[u][i];
    }
  }
  if (u == v) return u;
  for (int i = log; i >= 0; i--) {
    if (par[u][i] != -1 && par[u][i] != par[v][i]) {
      u = par[u][i];
      v = par[v][i];
    }
  }
  return par[v][0];
}
set<pair<int, int>> s;
void Del(int u, int l, int w) {
  if (ans1[u][l] < w) return;
  ans1[u][l] = 0;
  if (l == 0) {
    s.insert({u, par[u][l]});
    s.insert({par[u][l], u});
    return;
  }
  Del(u, l - 1, w);
  Del(par[u][l - 1], l - 1, w);
  ans1[u][l] = max(ans1[u][l - 1], ans1[par[u][l - 1]][l - 1]);
}
void Add(int u, int v, int w) {
  for (int i = 17; i >= 0; i--) {
    if (par[u][i] != -1 && depth[par[u][i]] >= depth[v]) {
      Del(u, i, w);
      u = par[u][i];
    }
  }
}
void solve() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; i++) {
    int x, y, w;
    scanf("%d%d%d", &x, &y, &w);
    tem.push_back(node(x, y, w, i));
  }
  kruskal();
  init(1);
  for (int i = 0; i < m; i++) {
    if (GorB[tem[i].id]) {
      continue;
    }
    if (query(tem[i].x, tem[i].y) == tem[i].w) {
      GorB[tem[i].id] = 1;
      int lc = lca(tem[i].x, tem[i].y);
      Add(tem[i].x, lc, tem[i].w);
      Add(tem[i].y, lc, tem[i].w);
    }
  }
  for (int i = 0; i < m; i++) {
    if (s.count({tem[i].x, tem[i].y})) GorB[tem[i].id] = 1;
  }
  for (int i = 1; i <= m; i++) {
    if (GorB[i] == 0) {
      printf("none\n");
    } else if (GorB[i] == 1) {
      printf("at least one\n");
    } else
      printf("any\n");
  }
}
int main() {
  int t = 1;
  solve();
  return 0;
}
