#include <bits/stdc++.h>
using namespace std;
const int maxn = 300010;
int Fir[maxn], Nxt[maxn << 1], Too[maxn << 1], w[maxn << 1], tot;
int n, q, root[maxn], fa[maxn], siz[maxn], dfn[maxn], son[maxn], ts, mp[maxn],
    top[maxn], vv[maxn], dep[maxn];
int adu[maxn << 1], adv[maxn << 1], adw[maxn << 1], in_tr[maxn << 1];
inline void Init() {
  for (int i = 1; i <= n; ++i) root[i] = i;
}
inline int find(int x) { return root[x] == x ? x : root[x] = find(root[x]); }
inline void merge(int x, int y) {
  x = find(x);
  y = find(y);
  root[x] = y;
}
inline bool connect(int x, int y) { return find(x) == find(y); }
inline void add(int a, int b, int c) {
  Too[++tot] = b;
  w[tot] = c;
  Nxt[tot] = Fir[a];
  Fir[a] = tot;
}
inline void dfs1(int u, int f) {
  fa[u] = f;
  siz[u] = 1;
  dep[u] = dep[f] + 1;
  for (int i = Fir[u]; i; i = Nxt[i]) {
    int v = Too[i];
    if (v == f) continue;
    dfs1(v, u);
    siz[u] += siz[v];
    vv[v] = w[i];
    if (siz[v] > siz[son[u]]) son[u] = v;
  }
}
inline void dfs2(int u, int tp) {
  top[u] = tp;
  dfn[u] = ++ts;
  mp[ts] = u;
  if (son[u]) dfs2(son[u], tp);
  for (int i = Fir[u]; i; i = Nxt[i]) {
    int v = Too[i];
    if (v != fa[u] && v != son[u]) dfs2(v, v);
  }
}
struct SegmentTree {
  int l, r, v, s, tag;
} tr[maxn << 2];
inline void pushup(int u) {
  tr[u].v = tr[(u << 1)].v ^ tr[(u << 1 | 1)].v;
  tr[u].s = tr[(u << 1)].s + tr[(u << 1 | 1)].s;
}
inline void change(int u) {
  tr[u].s = tr[u].r - tr[u].l + 1;
  tr[u].tag = 1;
}
inline void pushdown(int u) {
  if (tr[u].tag) {
    change((u << 1));
    change((u << 1 | 1));
    tr[u].tag = 0;
  }
}
inline void build(int u, int l, int r) {
  tr[u].l = l;
  tr[u].r = r;
  if (l == r) {
    tr[u].v = vv[mp[l]];
    return;
  }
  int mid = (l + r) >> 1;
  build((u << 1), l, mid);
  build((u << 1 | 1), mid + 1, r);
  pushup(u);
}
inline void modify(int u, int l, int r) {
  if (l <= tr[u].l && tr[u].r <= r) {
    change(u);
    return;
  }
  pushdown(u);
  int mid = (tr[u].l + tr[u].r) >> 1;
  if (l <= mid) modify((u << 1), l, r);
  if (mid < r) modify((u << 1 | 1), l, r);
  pushup(u);
}
inline int query(int u, int l, int r, int &cnt) {
  if (l <= tr[u].l && tr[u].r <= r) {
    cnt += tr[u].s;
    return tr[u].v;
  }
  pushdown(u);
  int mid = (tr[u].l + tr[u].r) >> 1, ans = 0;
  if (l <= mid) ans = query((u << 1), l, r, cnt);
  if (mid < r) ans ^= query((u << 1 | 1), l, r, cnt);
  return ans;
}
inline void add(int x, int y) {
  while (top[x] != top[y]) {
    if (dep[top[x]] <= dep[top[y]]) swap(x, y);
    modify(1, dfn[top[x]], dfn[x]);
    x = fa[top[x]];
  }
  if (dep[x] < dep[y]) swap(x, y);
  modify(1, dfn[son[y]], dfn[x]);
}
inline int ask(int x, int y, int w) {
  int ans = 0, sum = 0;
  while (top[x] != top[y]) {
    if (dep[top[x]] <= dep[top[y]]) swap(x, y);
    ans ^= query(1, dfn[top[x]], dfn[x], sum);
    x = fa[top[x]];
  }
  if (dep[x] < dep[y]) swap(x, y);
  ans ^= query(1, dfn[son[y]], dfn[x], sum);
  if (sum) return 0;
  return (ans ^ w) == 1;
}
int main() {
  scanf("%d%d", &n, &q);
  Init();
  for (int i = 1; i <= q; ++i) {
    scanf("%d%d%d", &adu[i], &adv[i], &adw[i]);
    if (!connect(adu[i], adv[i])) {
      add(adu[i], adv[i], adw[i]);
      add(adv[i], adu[i], adw[i]);
      in_tr[i] = 1;
      merge(adu[i], adv[i]);
    }
  }
  for (int i = 1; i <= n; ++i) find(root[i]);
  for (int i = 1; i <= n; ++i)
    if (root[i] == i) {
      dfs1(i, i);
      dfs2(i, i);
    }
  build(1, 1, n);
  for (int i = 1; i <= q; ++i) {
    if (in_tr[i])
      puts("YES");
    else {
      int x = adu[i], y = adv[i], w = adw[i];
      int ans = ask(x, y, w);
      puts(ans ? "YES" : "NO");
      if (ans) add(x, y);
    }
  }
  return 0;
}
