#include <iostream>
#include <vector>
using namespace std;

class unionfind{
    private:
        vector<int>par,r,sz;//父节点数组,秩(深度)数组,集合数组
        int count;
    public:
    //初始化
    unionfind(int n){
        count=n;
        par.resize(n);
        r.resize(n,0);
        sz.resize(n,1);
        for(int i=0;i<n;i++){
            par[i]=i;
        }
    }
    //查找
    int find(int i){
    // 路径压缩:在查找过程中将路径上的所有节点直接连接到根节点
    if(par[i]!=i){
        par[i]=find(par[i]);
    }
    return par[i];//找根
    }
    //合并
    void unionset(int a,int b){
        int x=find(a);
        int y=find(b);
        if(x==y){return;}
        if(r[x]>r[y]){
            par[y]=x;
            sz[x]+=sz[y];
        }else if (r[x]<r[y]) {
            par[x]=y;
            sz[y]+=sz[x];
        }else {
            par[y]=x;
            r[x]++;
            sz[x]+=sz[y];
        }
        count--;
    }
    //查询连通性
    bool isconnected(int x,int y){
        return find(x)==find(y);
    }
    //查询集合大小
    int getsetsize(int x){
        return sz[find(x)];
    }
    //获取集合数量
    // 额外功能
    int getCount() {
        return count;
    }
};

int main() {
    int n,q;
    cin>>n>>q;
    unionfind uf(n);
    for(int i=0;i<q;i++){
        int op;
        cin>>op;
        if(op==1){
        int i,j;
        cin>>i>>j;
        uf.unionset(i,j);
        }else if (op==2) {
        int i,j;
        cin>>i>>j;
        cout<<((uf.isconnected(i,j))?"YES":"NO")<<endl;
        }else if (op==3) {
        int i;
        cin>>i;
        cout<<uf.getsetsize(i)<<endl;
        }
    }
    return 0;
}