#include <bits/stdc++.h>
using namespace std;
template <class T, class L>
bool smax(T& x, L y) {
  return x < y ? (x = y, 1) : 0;
}
template <class T, class L>
bool smin(T& x, L y) {
  return y < x ? (x = y, 1) : 0;
}
const int maxn = 1e5 + 17, lg = 17;
int n, par[maxn][lg], h[maxn], ans[maxn], dsu[maxn];
bool mark[maxn];
vector<pair<int, int> > ass[maxn];
vector<int> g[maxn];
struct Q {
  int t, v, p, ind;
} qu[maxn];
int r(int v) { return ~dsu[v] ? dsu[v] = r(dsu[v]) : v; }
void mrg(int v, int u) {
  if ((v = r(v)) == (u = r(u))) return;
  dsu[v] = u;
}
int parat(int v, int hi) {
  for (int i = 0; i < lg; i++)
    if ((h[v] - hi) >> i & 1) v = par[v][i];
  return v;
}
void make_amirjoon_happy(int v, int p = -1) {
  mark[v] = 1;
  for (auto u : g[v])
    if (u != p) h[u] = h[*par[u] = v] + 1, make_amirjoon_happy(u);
}
int main() {
  ios::sync_with_stdio(0), cin.tie(0);
  memset(dsu, -1, sizeof dsu);
  int nq;
  cin >> n >> nq;
  int cnt3 = 0;
  for (int i = 0; i < nq; i++) {
    cin >> qu[i].t >> qu[i].v, qu[i].v--;
    if (qu[i].t == 3) {
      cin >> qu[i].ind, qu[i].ind--;
      ass[qu[i].ind].push_back({qu[i].v, cnt3++});
    }
    if (qu[i].t == 1) {
      cin >> qu[i].p, qu[i].p--;
      mark[qu[i].v] = 1;
      g[qu[i].p].push_back(qu[i].v);
    }
  }
  for (int v = 0; v < n; v++)
    if (!mark[v]) make_amirjoon_happy(v);
  for (int i = 1; i < lg; i++)
    for (int v = 0; v < n; v++) par[v][i] = par[par[v][i - 1]][i - 1];
  int cnt2 = 0;
  for_each(qu, qu + nq, [&cnt2](Q& q) {
    if (q.t == 1)
      mrg(q.v, q.p);
    else if (q.t == 2) {
      for (auto c : ass[cnt2]) {
        ans[c.second] =
            r(q.v) == r(c.first) && parat(q.v, h[c.first]) == c.first;
      }
      cnt2++;
    }
  });
  for (int i = 0; i < cnt3; i++) cout << (ans[i] ? "YES" : "NO") << '\n';
  return 0;
}
