blablabla
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 100010;
int p[N], si[N];
int n, m;
char op[2];
void init() //初始化,一开始没有边,即每个点的父节点此时都是自己,每个点都是一个连通块,故顶点i所在连通块的数量为1
{
for(int i = 1; i <= n; ++i)
{
p[i] = i;
si[i] = 1;//以后该数组仅仅对该连通块的祖先节点有效
}
}
int find(int x) //找到顶点x的祖先节点 + 路径压缩
{
if(p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main()
{
cin>>n>>m;
init();
while(m--)
{
int a, b;
scanf("%s", op);
if(op[0] == 'C')
{
scanf("%d%d", &a, &b);
// if(a == b) //此处不仅仅是 a == b 而是如果如果顶点a所在连通块的祖先节点 == 顶点b所在连通块的祖先节点的话
if(find(a) == find(b)) //因为a b 不等,但是a 与 b所在同一个连通块。就是造成 下面第二行变成顶点的二倍
continue;
si[find(b)] += si[find(a)]; //顶点a所在连通块的点放在顶点b所在连通块中
p[find(a)] = find(b); //顶点a所在连通块的祖先节点的父节点为顶点b所在连通块的祖先节点
}
else if(op[1] == '1')
{
scanf("%d%d", &a, &b);
if(find(a) == find(b)) //如果顶点a所在连通块的祖先节点 == 顶点b所在连通块的祖先节点的话
puts("Yes");
else
puts("No");
}
else
{
cin>>a;
cout<<si[find(a)]<<endl;
}
}
return 0;
}