#include<iostream>
#include<cmath>
#include<map>
#include<set>
#include<utility>
#include<numeric>
#include<vector>
#include<unordered_map>
 
using namespace std;
 
int par[41234];
 
template<class E>
int find(E &par,int x){
  return (par[x]==x)?x:par[x]=find(par,par[x]);
}
 
template<class E>
void unite(E &par,int a,int b){
  par[find(par,a)]=find(par,b);
}    
 
int main(){
  int n,k;
  cin>>n>>k;
  int q[41234],u[41234],v[41234];
  for(int i=0;i<k;i++){
    cin>>q[i]>>u[i]>>v[i];
  }
  for(int i=0;i<k;){
    int l=min<int>(k,i+sqrt(k));
    set<pair<int,int> > qs;
    set<int> app;
    for(int j=i;j<l;j++){
      app.insert(u[j]);
      app.insert(v[j]);
      if(q[j]!=3){
	qs.insert(make_pair(u[j],v[j]));
      }
    }
    iota(begin(par),end(par),0);
    set<pair<int,int> > reg;
    vector<pair<int,int> >con;
    for(int j=i-1;j>=0;j--){
      if(q[j]!=3&&reg.insert(make_pair(u[j],v[j])).second&&q[j]==1){
	if(!qs.count(make_pair(u[j],v[j]))){
	  unite(par,u[j],v[j]);
	}else{
	  con.emplace_back(u[j],v[j]);
	}
      }
    }
    int ocpar[41234];
    for(auto e:app){
      ocpar[e]=e;
    }
    for(auto e:app){
      for(auto f:app){
	if(find(par,e)==find(par,f)){
	  unite(ocpar,e,f);
	}
      }
    }
    for(int j=i;j<l;j++){
      if(q[j]==3){
	int cpar[41234];
	for(auto e:app){
	  cpar[e]=ocpar[e];
	}
	set<pair<int,int> > used;
	for(int k=j-1;k>=i;k--){
	  if(q[k]!=3&&used.insert(make_pair(u[k],v[k])).second&&q[k]==1){
	    unite(cpar,u[k],v[k]);
	  }
	}
	for(auto e:con){
	  if(!used.count(e)){
	    unite(cpar,e.first,e.second);
	  }
	}
	cout<<((find(cpar,u[j])==find(cpar,v[j]))?"YES":"NO")<<endl;
      }
    }
    i=l;
  }
}