#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int INF = 1e9;
const ll LINF = 1e18;
template<class S,class T> ostream& operator << (ostream& out,const pair<S,T>& o){ out << "(" << o.first << "," << o.second << ")"; return out; }
template<class T> ostream& operator << (ostream& out,const vector<T> V){ for(int i = 0; i < V.size(); i++){ out << V[i]; if(i!=V.size()-1) out << " ";} return out; }
template<class T> ostream& operator << (ostream& out,const vector<vector<T> > Mat){ for(int i = 0; i < Mat.size(); i++) { if(i != 0) out << endl; out << Mat[i];} return out; }
template<class S,class T> ostream& operator << (ostream& out,const map<S,T> mp){ out << "{ "; for(auto it = mp.begin(); it != mp.end(); it++){ out << it->first << ":" << it->second; if(mp.size()-1 != distance(mp.begin(),it)) out << ", "; } out << " }"; return out; }

class PartParsistentUnionFind{
    typedef pair<int,int> pii;
private:
    vector<int> par;
    vector<int> time;
    vector<vector<pii>> size;
    int now;
public:
    PartParsistentUnionFind(){}
    PartParsistentUnionFind(int N){init(N);}
    void init(int N){
        par.clear(); time.clear(); size.clear();
        par.assign(N,0);
        time.resize(N,INT_MAX);
        size.assign(N,vector<pii>(1,{0,1}));
        now = 0;
    }
    int find(int x,int T = INT_MAX){
        if(T == INT_MAX) T = now;
        if(time[x] > T) return x;
        else return find(par[x],T);
    }
    bool unite(int x,int y){
        now++;
        x = find(x,now); y = find(y,now);
        if(x == y) return false;
        if(par[x] < par[y]) swap(x,y);
        par[x] += par[y];
        par[y] = x;
        time[y] = now;
        size[x].push_back({now,par[x]});
        return true;
    }
    int Getnow(){ return now; }
    int Getsize(int x,int T = INT_MAX){
        if(T == INT_MAX) T = now;
        int ret = (int)(upper_bound(size[x].begin(),size[x].end(),pii(T,INT_MAX)) - size[x].begin());
        return ret;
    }
    pii GetInfo(int x,int T = INT_MAX){
        if(T == INT_MAX) T = now;
        int idx = (int)(upper_bound(size[x].begin(),size[x].end(),pii(T,INT_MAX)) - size[x].begin()) - 1;
        pii ret = size[x][idx];
        return ret;
    }
    bool same(int x,int y,int T = INT_MAX){
        if(T == INT_MAX) T = now;
        return find(x,T) == find(y,T);
    }
};

struct UnionFind {
    vector<int> data;
    UnionFind(int size) : data(size, -1) { }
    bool unionSet(int x, int y) {
        x = root(x); y = root(y);
        if (x != y) {
            if (data[y] < data[x]) swap(x, y);
            data[x] += data[y]; data[y] = x;
        }
        return x != y;
    }
    bool findSet(int x, int y) {
        return root(x) == root(y);
    }
    int root(int x) {
        return data[x] < 0 ? x : data[x] = root(data[x]);
    }
    int size(int x) {
        return -data[root(x)];
    }
};

void solve1(){
    int n,q; cin >> n >> q;
    UnionFind UF(n);
    while(q--){
        int com; cin >> com;
        int x,y; cin >> x >> y;
        if(com == 0){
            UF.unionSet(x, y);
      //      cout << " : " << UF.size(x) << endl;
        }else{
            cout << UF.findSet(x, y) << endl;
        }
    }
}
void solve2(){
    int n,q; cin >> n >> q;
    PartParsistentUnionFind PPUF(n);
    while(q--){
        int com; cin >> com;
        int x,y; cin >> x >> y;
        if(com == 0){
            PPUF.unite(x, y);
//            for(int i = 0; i < n; i++){
//                cout << i << " : " << PPUF.find(i) << endl;
//            }
        }else{
//            cout << x << " " << y << endl;
            cout << PPUF.same(x,y) << endl;
      //      cout << PPUF.findSet(x, y) << endl;
        }
    }
}
int main(void) {
    cin.tie(0); ios_base::sync_with_stdio(false);
 //   solve1();
    solve2();
    return 0;
}



Measured memory_bytes: 3852