#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cmath>
#include <iomanip>
#include <cassert>
#include <bitset>
using namespace std;

typedef pair<int, int> P;
#define rep(i, n) for (int i=0; i<(n); i++)
#define all(c) (c).begin(), (c).end()
#define uniq(c) c.erase(unique(all(c)), (c).end())
#define index(xs, x) (int)(lower_bound(all(xs), x) - xs.begin())
#define _1 first
#define _2 second
#define pb push_back
#define INF 1145141919
#define MOD 1000000007
const int B = 200;

int N, Q;
int U[40000], R[40000];
int find(int x) {
  if (U[x] == x) return x;
  return U[x] = find(U[x]);
}
void unite(int x, int y) {
  x = find(x), y = find(y);
  if (x == y) return;
  if (R[x] < R[y]) swap(x, y);
  U[x] = y;
}

int QT[40000], QU[40000], QV[40000];
bool used[40000];
set<int> G[40000];

void dfs(int x) {
  used[x] = true;
  for (int t : G[x]) if (!used[t]) dfs(t);
}

signed main() {
  ios::sync_with_stdio(false); cin.tie(0);
  cin >> N >> Q;
  rep(i, Q) {
    cin >> QT[i] >> QU[i] >> QV[i];
  }
  set<P> edges;
  vector<int> vs;
  vector<P> dyn;
  rep(q, Q) {
    if (q%B == 0) {
      rep(i, N) U[i] = i, R[i] = 1, G[i].clear();
      rep(i, N) used[i] = true;
      vs.clear();
      dyn.clear();
      for (int i=q; i<min(q+B, Q); i++) {
        vs.pb(QU[i]);
        vs.pb(QV[i]);
        dyn.pb(P(QU[i], QV[i]));
      }
      sort(all(vs)); uniq(vs);
      sort(all(dyn)); uniq(dyn);
      for (P p : edges) if (!binary_search(all(dyn), p)) unite(p._1, p._2);
      for (P p : edges) if (binary_search(all(dyn), p)) {
        int u = find(p._1), v = find(p._2);
        G[u].insert(v);
        G[v].insert(u);
      }
    }
    int u = find(QU[q]), v = find(QV[q]);
    if (QT[q] == 1) {
      edges.insert(P(QU[q], QV[q]));
      G[u].insert(v);
      G[v].insert(u);
    }
    else if (QT[q] == 2) {
      edges.erase(P(QU[q], QV[q]));
      G[u].erase(v);
      G[v].erase(u);
    }
    else {
      for (int x : vs) used[find(x)] = false;
      dfs(u);
      if (used[v]) cout << "YES\n";
      else cout << "NO\n";
    }
  }
  return 0;
}

