#include <bits/stdc++.h>
using namespace std;
template <class T>
bool ckmin(T &a, const T &b) {
  return a > b ? a = b, 1 : 0;
}
template <class T>
bool ckmax(T &a, const T &b) {
  return a < b ? a = b, 1 : 0;
}
namespace debug {
void __print(int x) { cerr << x; }
void __print(long long x) { cerr << x; }
void __print(double x) { cerr << x; }
void __print(long double x) { cerr << x; }
void __print(char x) { cerr << '\'' << x << '\''; }
void __print(const string &x) { cerr << '\"' << x << '\"'; }
void __print(const char *x) { cerr << '\"' << x << '\"'; }
void __print(bool x) { cerr << (x ? "true" : "false"); }
template <typename T, typename V>
void __print(const pair<T, V> &x) {
  cerr << '{';
  __print(x.first);
  cerr << ',';
  __print(x.second);
  cerr << '}';
}
template <typename T>
void __print(const T &x) {
  int f = 0;
  cerr << '{';
  for (auto z : x) cerr << (f++ ? "," : ""), __print(z);
  cerr << "}";
}
void _print() { cerr << "]\n"; }
template <typename T, typename... V>
void _print(T t, V... v) {
  __print(t);
  if (sizeof...(v)) cerr << ", ";
  _print(v...);
}
}  // namespace debug
using namespace debug;
const char nl = '\n';
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
const int mxN = 3e5 + 12;
int dsu[mxN], vel[mxN];
int findSet(int u) {
  if (u == dsu[u]) return u;
  return dsu[u] = findSet(dsu[u]);
}
bool unite(int u, int v) {
  u = findSet(u);
  v = findSet(v);
  if (u == v) return 0;
  if (vel[u] > vel[v]) swap(u, v);
  dsu[u] = v;
  vel[v] += vel[u];
  return 1;
}
vector<pair<int, int>> adj[mxN];
const int LOG = 26;
int timer = -1;
int tin[mxN], tout[mxN];
int lift[mxN][LOG];
bool vis[mxN];
int ksor[mxN];
void dfs(int s, int p = -1, int tren = 0) {
  vis[s] = 1;
  tin[s] = ++timer;
  lift[s][0] = p;
  for (int i = 1; i < LOG; ++i) {
    if (lift[s][i - 1] == -1) {
      lift[s][i] = -1;
      continue;
    }
    lift[s][i] = lift[lift[s][i - 1]][i - 1];
  }
  ksor[s] = tren;
  for (auto e : adj[s]) {
    if (e.first == p) continue;
    dfs(e.first, s, tren ^ e.second);
  }
  tout[s] = timer;
}
bool isAncestor(int u, int v) { return tin[u] <= tin[v] && tout[u] >= tout[v]; }
int lca(int u, int v) {
  if (isAncestor(u, v)) return u;
  if (isAncestor(v, u)) return v;
  for (int i = LOG - 1; i >= 0; --i) {
    if (lift[u][i] == -1) continue;
    if (!isAncestor(lift[u][i], v)) {
      u = lift[u][i];
    }
  }
  return lift[u][0];
}
int ft[mxN + 12];
void update(int i, int x) {
  for (; i <= mxN; i += i & -i) {
    ft[i] += x;
  }
}
int query(int i) {
  int r = 0;
  for (; i; i -= i & -i) {
    r += ft[i];
  }
  return r;
}
void odradi(int u, int v) {
  while (u != v) {
    update(tin[u], 1);
    update(tout[u] + 1, -1);
    u = lift[u][0];
  }
}
void solve() {
  int n, q;
  cin >> n >> q;
  for (int i = 0; i < n; ++i) {
    dsu[i] = i;
    vel[i] = 1;
  }
  vector<array<int, 3>> upit(q);
  for (auto &z : upit) {
    for (int i = 0; i < 3; ++i) cin >> z[i];
    --z[0], --z[1];
  }
  vector<bool> ans(q);
  for (int i = 0; i < q; ++i) {
    int u = upit[i][0];
    int v = upit[i][1];
    int x = upit[i][2];
    if (unite(u, v)) {
      ans[i] = 1;
      adj[u].push_back({v, x});
      adj[v].push_back({u, x});
    }
  }
  for (int i = 0; i < n; ++i) {
    if (!vis[i]) {
      dfs(i);
    }
  }
  for (int i = 0; i < q; ++i) {
    if (ans[i]) continue;
    int u = upit[i][0];
    int v = upit[i][1];
    int x = upit[i][2];
    int izraz = ksor[u] ^ ksor[v];
    izraz ^= x;
    if (izraz == 0) continue;
    int rodjak = lca(u, v);
    int suma = query(tin[u]) + query(tin[v]) - 2 * query(tin[rodjak]);
    if (suma > 0) continue;
    ans[i] = 1;
    odradi(u, rodjak);
    odradi(v, rodjak);
  }
  for (auto z : ans) cout << (z ? "YES" : "NO") << nl;
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int testCases = 1;
  while (testCases--) solve();
}
