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

//手写一个并查集
class UnionFind{
    private:
    vector<int> parent;//parent[i]记录节点i的父节点
    vector<int> size;  //size[i]记录以结点i为根的数的大小

    public:
    UnionFind(int n){//构造函数,确定parent和size数组的大小,确定并查集的容量
        parent.resize(n);
        size.resize(n, 1);//初始时每个元素自己组成一个集合,所在集合大小均为1
        //parent中每个结点的父节点均为自己
        for(int i = 0; i < n; i++){
            parent[i] = i;
        }
    }

    //查找函数,查找结点i所在树的根节点
    int Find(int i){
        if(parent[i] != i){
            parent[i] = Find(parent[i]);//递归查找,路径压缩
        }
        return parent[i];
    }

    //合并函数,合并两个集合
    void Uni(int i, int j){
        int rooti = Find(i);
        int rootj = Find(j);
        if(rooti == rootj){
            return;
        }
        else if(size[rooti] > size[rootj]){//按照大小合并,大小小的合并到大小大的集合中
            parent[rootj] = rooti;
            size[rooti] += size[rootj];
            return;
        }
        else{
            parent[rooti] = rootj;
            size[rootj] += size[rooti];
            return;
        }
    }

    //查询大小函数,返回元素i所在集合的大小
    int Size(int i){
        int x = Find(i);
        return size[x];
    }
 
};

int main() {
    //输入数据
    int n, q;
    cin >> n >> q;
    
    //初始化并查集
    UnionFind uf(n + 1);

    //处理q行指令
    for(int i = 0; i < q; i++){
        int op;
        cin >> op;
        if(op == 1){
            int i, j;
            cin >> i >> j;
            uf.Uni(i, j);
        }
        else if(op == 2){
            int i, j;
            cin >> i >> j;
            if(uf.Find(i) == uf.Find(j)){
                cout << "YES" << '\n';
            }
            else{
                cout << "NO" << '\n';
            }
        }
        else{
            int i;
            cin >> i;
            cout << uf.Size(i) << '\n';
        }
    }

    return 0;
}
// 64 位输出请用 printf("%lld")