#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int n, num, m, cnt = 1, nq[maxn], qn[maxn], l[maxn], r[maxn], f[maxn],
               deg[maxn];
vector<int> nei[maxn];
vector<int> q[maxn];
pair<int, pair<int, int> > p[maxn];
bool mark[maxn], ans[maxn];
int root(int v) { return f[v] < 0 ? v : f[v] = root(f[v]); }
void merge(int v, int u) {
  if ((v = root(v)) == (u = root(u))) return;
  if (-f[v] > -f[u]) swap(u, v);
  f[u] += f[v];
  f[v] = u;
}
void dfs(int v, int par) {
  mark[v] = true;
  l[v] = cnt++;
  for (auto u : nei[v])
    if (u == par)
      continue;
    else if (l[u] == 0)
      dfs(u, v);
  r[v] = cnt++;
}
void dfs_all() {
  for (int i = 1; i <= n; i++)
    if (!mark[i] && deg[i] == 0) cnt = 1, dfs(i, -1);
}
bool parent(int u, int v) {
  if (root(u) == root(v) && l[u] <= l[v] && r[v] <= r[u]) return true;
  return false;
}
int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  memset(f, -1, sizeof f);
  cin >> n >> m;
  for (int i = 1; i <= m; i++) {
    cin >> p[i].first;
    if (p[i].first == 1)
      cin >> p[i].second.first >> p[i].second.second,
          nei[p[i].second.second].push_back(p[i].second.first),
          deg[p[i].second.first]++;
    else if (p[i].first == 2)
      cin >> p[i].second.first, qn[i] = ++num, nq[num] = i;
    else {
      cin >> p[i].second.first >> p[i].second.second;
      q[p[i].second.second].push_back(i);
    }
  }
  dfs_all();
  for (int i = 1; i <= m; i++) {
    if (p[i].first == 1)
      merge(p[i].second.first, p[i].second.second);
    else if (p[i].first == 2) {
      int c = qn[i], v = p[i].second.first;
      for (auto j : q[c]) {
        int u = p[j].second.first;
        ans[j] = (root(v) == root(u) && parent(u, v));
      }
    }
  }
  for (int i = 1; i <= m; i++)
    if (p[i].first == 3) cout << (ans[i] ? "YES\n" : "NO\n");
}
