#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5, lg = 25;
int par[maxn][lg], cnt;
vector<int> subtree[maxn][lg];
pair<int, int> pac[maxn];
void dfs(int v, int h) {
  int p = max(1, h);
  for (int i = p;; ++i) {
    par[v][i] = par[par[v][i - 1]][i - 1];
    if (par[v][i] == -1) {
      break;
    } else {
      subtree[par[v][i]][i].push_back(v);
    }
  }
  for (auto i : subtree[v][h]) {
    dfs(i, h + 1);
  }
}
inline int goup(int v) {
  for (int i = lg - 1; i >= 0; --i) {
    if (par[v][i] != -1) {
      v = par[v][i++];
    }
  }
  return v;
}
int geth(int v) {
  int ans = 0;
  for (int i = lg - 1; i >= 0; --i) {
    if (par[v][i] != -1) {
      v = par[v][i];
      ans += (1ll << (i++));
    }
  }
  return ans;
}
inline bool isunder(int v, int u) {
  int h1 = geth(v), h2 = geth(u);
  for (int i = lg - 1; i >= 0; i--) {
    if (par[v][i] != -1 && h1 - (1ll << i) >= h2) {
      v = par[v][i];
      h1 -= (1LL << (i++));
    }
  }
  if (v == u) {
    return 1;
  }
  return 0;
}
int main() {
  memset(par, -1, sizeof(par));
  int n, m;
  cin >> n >> m;
  while (m--) {
    int type, x, y;
    cin >> type;
    if (type == 1) {
      cin >> x >> y;
      x--;
      y--;
      par[x][0] = y;
      subtree[y][0].push_back(x);
      dfs(x, 0);
    }
    if (type == 2) {
      cin >> x;
      x--;
      int u = goup(x);
      pac[cnt++] = {x, u};
    }
    if (type == 3) {
      cin >> x >> y;
      x--;
      y--;
      int v = pac[y].first, u = pac[y].second;
      if ((isunder(v, x) && isunder(x, u)) || x == v || x == u) {
        cout << "YES" << endl;
      } else {
        cout << "NO" << endl;
      }
    }
  }
}
