#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, m;
vector<pair<int, int>> ad[N];
int id[N], cnt, dd[N];
vector<tuple<int, int, int>> que;
pair<int, int> g[N];
int pd[N][22], dep[N], mi[N][22];
int root(int x) { return id[x] < 0 ? x : id[x] = root(id[x]); }
bool mer(int u, int v) {
  if ((u = root(u)) == (v = root(v))) return false;
  if (id[u] < id[v]) swap(u, v);
  id[u] += id[v];
  id[v] = u;
  return true;
}
void dfs(int u) {
  for (int i = 1, _c = 20; i <= _c; ++i)
    pd[u][i] = pd[pd[u][i - 1]][i - 1],
    mi[u][i] = max(mi[u][i - 1], mi[pd[u][i - 1]][i - 1]);
  for (auto &v : ad[u]) {
    pd[v.first][0] = u;
    mi[v.first][0] = v.second;
    dep[v.first] = dep[u] + 1;
    dfs(v.first);
  }
}
int lca(int u, int v) {
  if (dep[u] < dep[v]) swap(u, v);
  int _ = dep[u] - dep[v];
  for (int i = 20, _c = 0; i >= _c; --i)
    if (_ >> i & 1) u = pd[u][i];
  if (u == v) return u;
  for (int i = 20, _c = 0; i >= _c; --i)
    if (pd[u][i] != pd[v][i]) u = pd[u][i], v = pd[v][i];
  return pd[u][0];
}
int get(int u, int v) {
  if (dep[u] < dep[v]) swap(u, v);
  int ret = 0, _ = dep[u] - dep[v];
  for (int i = 20, _c = 0; i >= _c; --i)
    if (_ >> i & 1ll) {
      ret = max(ret, mi[u][i]);
      u = pd[u][i];
    }
  if (u == v) return ret;
  for (int i = 20, _c = 0; i >= _c; --i)
    if (pd[u][i] != pd[v][i]) {
      ret = max({ret, mi[u][i], mi[v][i]});
      u = pd[u][i], v = pd[v][i];
    }
  ret = max({ret, mi[u][0], mi[v][0]});
  return ret;
}
int32_t main() {
  ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  cin >> n >> m;
  memset(id, -1, sizeof(id));
  for (int i = 1, _c = m; i <= _c; ++i) {
    int t, x, y;
    cin >> t;
    if (t == 1) {
      cin >> x >> y;
      ad[y].emplace_back(x, i);
      mer(x, y);
      dd[x] = 1;
    } else if (t == 2) {
      cin >> x;
      g[++cnt] = make_pair(x, i);
    } else {
      cin >> x >> y;
      que.push_back(make_tuple(mer(x, g[y].first), x, y));
    }
  }
  for (int i = 1, _c = n; i <= _c; ++i)
    if (!dd[i]) dfs(i);
  for (auto &_ : que) {
    int t, u, v;
    tie(t, u, v) = _;
    int x = g[v].first;
    if (t)
      cout << "NO\n";
    else if (lca(u, x) == u && get(u, x) <= g[v].second)
      cout << "YES\n";
    else
      cout << "NO\n";
  }
}
