#include <bits/stdc++.h>
using namespace std;
inline void inpint(int &n) {
  n = 0;
  register int ch = getchar_unlocked();
  bool sign = 0;
  while (ch < 48 || ch > 57) {
    if (ch == '-') sign = 1;
    ch = getchar_unlocked();
  }
  while (ch >= 48 && ch <= 57) {
    n = (n << 3) + (n << 1) + ch - 48, ch = getchar_unlocked();
  }
  if (sign) n = -n;
}
inline int sqr(int x) { return x * x; }
inline int cube(int x) { return x * x * x; }
inline long long sqrLL(long long x) { return x * x; }
inline long long cubeLL(long long x) { return x * x * x; }
const long long LLINF = 9223372036854775807LL;
const long long LLINF17 = 100000000000000000LL;
const int INF = 2147483647;
const int INF9 = 1000000000;
const int MOD = 1000000007;
const double eps = 1e-7;
const double PI = acos(-1.0);
int dr[] = {1, 0, -1, 0, -1, 1, 1, -1};
int dc[] = {0, -1, 0, 1, 1, 1, -1, -1};
int n, m;
pair<int, pair<int, int> > query[100005];
vector<int> graph[100005];
int par[100005], doc[100005], docit = 0;
vector<pair<int, int> > checksign[100005];
bool flag[100005];
int dfsin[200005], dfsout[200005], it = 0;
int dpar[100005];
inline int root(int x) {
  if (dpar[x] == x) return dpar[x];
  return dpar[x] = root(dpar[x]);
}
inline void link(int x, int y) { dpar[root(x)] = root(y); }
inline bool issameset(int x, int y) { return root(x) == root(y); }
inline void dfs(int node) {
  flag[node] = 1;
  dfsin[node] = ++it;
  for (int i = 0; i < (int)graph[node].size(); i++) {
    int next = graph[node][i];
    if (flag[next]) continue;
    dfs(next);
  }
  dfsout[node] = ++it;
}
bool ans[100005];
int main() {
  cin >> n >> m;
  for (int i = 1; i <= m; i++) {
    cin >> query[i].first;
    if (query[i].first == 1) {
      cin >> query[i].second.first >> query[i].second.second;
      par[query[i].second.first] = query[i].second.second;
      graph[query[i].second.second].push_back(query[i].second.first);
    } else if (query[i].first == 2) {
      cin >> query[i].second.first;
      doc[++docit] = query[i].second.first;
    } else if (query[i].first == 3) {
      cin >> query[i].second.first >> query[i].second.second;
      checksign[query[i].second.second].push_back(
          make_pair(i, query[i].second.first));
    }
  }
  for (int i = 1; i <= n; i++) {
    dpar[i] = i;
    if (!flag[i] && !par[i]) dfs(i);
  }
  int doccnt = 0;
  for (int i = 1; i <= m; i++) {
    if (query[i].first == 1) {
      link(query[i].second.first, query[i].second.second);
    } else if (query[i].first == 2) {
      ++doccnt;
      int getnode = query[i].second.first;
      for (int j = 0; j < (int)checksign[doccnt].size(); j++) {
        int parnode = checksign[doccnt][j].second;
        if (issameset(parnode, getnode) && dfsin[parnode] <= dfsin[getnode] &&
            dfsout[getnode] <= dfsout[parnode]) {
          ans[checksign[doccnt][j].first] = 1;
        }
      }
    }
  }
  for (int i = 1; i <= m; i++) {
    if (query[i].first == 3) {
      if (ans[i])
        puts("YES");
      else
        puts("NO");
    }
  }
  return 0;
}
