#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ref(i,n,x) for(int i=x;i>=n;i--)
#define fo(i, n, x) for (int i = x; i <= n; i++)
struct DSU {
vector<int> f; // f[i]表示i的父节点(用于找根节点)
vector<int> siz; // siz[i]表示以i为根的集合大小
DSU() {}
DSU(int n) { init(n); } // 构造函数初始化n个节点
void init(int n) { // 初始化:每个节点自成一个集合
f.resize(n+1); // 节点编号从1开始(预留0索引)
iota(f.begin(), f.end(), 0); // f[i] = i(父节点指向自己)
siz.assign(n, 1); // 每个集合大小初始为1
}
int find(int x) { // 找x的根节点,带路径压缩(优化查询效率)
while (x != f[x]) {
x = f[x] = f[f[x]]; // 路径压缩:让x直接指向祖父节点
}
return x;
}
bool same(int x, int y) { // 判断x和y是否在同一个集合(连通)
return find(x) == find(y);
}
bool merge(int x, int y) { // 合并x和y所在的集合
x = find(x), y = find(y);
if (x == y) return false; // 已在同一集合,无需合并
siz[x] += siz[y]; // 合并集合大小
f[y] = x; // y的根节点指向x的根节点
return true;
}
int size(int x) { // 返回x所在集合的大小
return siz[find(x)];
}
};
void solve(){
int n,m;
cin>>n>>m;
DSU dsu(n);
dsu.init(n);
fo(i,m,1){
int z,x,y;
cin>>z>>x>>y;
if(z==1){
dsu.merge(x,y);
}
if(z==2){
if(dsu.same(x,y))cout<<"Y"<<endl;
else cout<<"N"<<endl;
}
}
}
signed main(){
int t=1;
//cin>>t;
while(t--)solve();
return 0;
}