#include <bits/stdc++.h>
using namespace std;
const int maxn = 2000 * 100 + 10;
int par[maxn], st[maxn], ft[maxn], tim, type[maxn], x[maxn], y[maxn], num[maxn],
    doc[maxn];
bool mark[maxn], f[maxn];
pair<int, int> req[maxn];
vector<int> e[maxn], vec[maxn];
int find_root(int v) {
  if (par[v] == -1) return v;
  return par[v] = find_root(par[v]);
}
void dfs(int v) {
  mark[v] = true;
  st[v] = ++tim;
  for (int i = 0; i < e[v].size(); i++) {
    int u = e[v][i];
    if (!mark[u]) dfs(u);
  }
  ft[v] = tim;
  return;
}
int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  int n, m, cnt = 0;
  cin >> n >> m;
  fill(par, par + n + 1, -1);
  for (int i = 1; i <= m; i++) {
    cin >> type[i];
    if (type[i] == 1) cin >> x[i] >> y[i];
    if (type[i] == 2) cin >> x[i];
    if (type[i] == 3) {
      cin >> x[i] >> num[i];
      vec[num[i]].push_back(i);
      cnt++;
    }
  }
  int prvnd = 1;
  for (int i = 0; i < m; i++) {
    if (type[i] == 1) {
      par[x[i]] = y[i];
      e[y[i]].push_back(x[i]);
    }
    if (type[i] == 2) {
      doc[prvnd] = x[i];
      for (int j = 0; j < vec[prvnd].size(); j++) {
        int ind = vec[prvnd][j];
        int root1 = find_root(x[ind]), root2 = find_root(x[i]);
        f[ind] = (root1 == root2);
        req[ind] = {x[ind], prvnd};
      }
      prvnd++;
    }
  }
  for (int i = 1; i <= n; i++) {
    if (!mark[i]) {
      tim = 0;
      int root = find_root(i);
      dfs(root);
    }
  }
  for (int i = 1; i <= m; i++) {
    if (type[i] != 3) continue;
    int xx = req[i].first, numm = req[i].second;
    if (!f[i])
      cout << "NO" << endl;
    else {
      if (st[doc[numm]] >= st[xx] && ft[doc[numm]] <= ft[xx])
        cout << "YES" << endl;
      else
        cout << "NO" << endl;
    }
  }
  return 0;
}
