Problem:
Disjoint Set

Write a program which manipulates a disjoint set S = {S1, S2, . . . , Sk}.

First of all, the program should read an integer n, then make a disjoint set where each element consists of 0, 1, ... n−1 respectively.

Next, the program should read an integer q and manipulate the set for q queries. There are two kinds of queries for different operations:

unite(x, y): unites sets that contain x and y, say Sx and Sy, into a new set.

same(x, y): determine whether x and y are in the same set.

Input

n q
com1 x1 y1
com2 x2 y2
...
comq xq yq

In the first line, n and q are given. Then, q queries are given where com represents the type of queries. '0' denotes unite and '1' denotes same operation.

Output

For each same operation, print 1 if x and y are in the same set, otherwise 0, in a line.

Constraints

1 ≤ n ≤ 10000

1 ≤ q ≤ 100000

x ≠ y

Sample Input

5 12
0 1 4
0 2 3
1 1 2
1 3 4
1 1 4
1 3 2
0 1 3
1 2 4
1 3 0
0 0 4
1 0 2
1 3 0

Sample Output

0
0
1
1
1
0
1
1

Solution in C++11 (judge verdict: Accepted)

#include <bits/stdc++.h>
#define ll long long
#define INF 1000000005
#define MOD 1000000007
#define EPS 1e-10
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define rrep(i,n) for(int i=(int)(n)-1;i>=0;--i)
#define srep(i,s,t) for(int i=(int)(s);i<(int)(t);++i)
#define each(a,b) for(auto (a): (b))
#define all(v) (v).begin(),(v).end()
#define len(v) (int)(v).size()
#define zip(v) sort(all(v)),v.erase(unique(all(v)),v.end())
#define cmx(x,y) x=max(x,y)
#define cmn(x,y) x=min(x,y)
#define fi first
#define se second
#define pb push_back
#define show(x) cout<<#x<<" = "<<(x)<<endl
#define spair(p) cout<<#p<<": "<<p.fi<<" "<<p.se<<endl
#define svec(v) cout<<#v<<":";rep(kbrni,v.size())cout<<" "<<v[kbrni];cout<<endl
#define sset(s) cout<<#s<<":";each(kbrni,s)cout<<" "<<kbrni;cout<<endl
#define smap(m) cout<<#m<<":";each(kbrni,m)cout<<" {"<<kbrni.first<<":"<<kbrni.second<<"}";cout<<endl

using namespace std;

typedef pair<int,int> P;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<double> vd;
typedef vector<P> vp;
typedef vector<string> vs;

const int MAX_N = 100005;

//???????????????????????????????????¨??¨????????¨?????????????????????????????????
//??????splay??¨??????????????¨???????????????????????????????????????

struct node {
    node* left; node* right; node* par;
    bool rev;
    int val,size;
    node(int t) : left(nullptr), right(nullptr), par(nullptr), rev(false), val(t), size(1){}
    //?????????????????????????????????
    bool isRoot(){
        return (!par) || (par->left != this && par->right != this);
    }
    //????????¬?????¨????????¢?????????
    void push(){
        if(rev){
            rev = false;
            swap(left,right);
            if(left){
                left->rev = !(left->rev);
            }
            if(right){
                right->rev = !(right->rev);
            }
        }
    }
};

class LinkCutTree{
private:
    int getSize(node *u){
        return u?u->size:0;
    }
    void updateSize(node *u){
        u->size = 1 + getSize(u->left) + getSize(u->right);
    }
    //ch??¨p???????????¢????????????(lch:?????????????????????)
    void connect(node* ch, node* p, bool lch){
        if(ch){
            ch->par = p;
        }
        if(lch){
            p->left = ch;
        }else{
            p->right = ch;
        }
    }
    //zig, zig-zag, zig-zig ???????¨????????????¢?????¨???
    void rotate(node* u){
        node* p = u->par;
        node* gp  = p->par;
        bool isRootP = p->isRoot();
        bool lch = (u == p->left);
        connect(lch ? (u->right) : (u->left),p,lch);
        connect(p,u,!lch);
        updateSize(p);
        updateSize(u);
        if(isRootP){
            //zig-step
            u->par = gp;
        }else{
            //zig-zag or zig-zig step
            connect(u,gp,(p == gp->left));
            updateSize(u);
        }
    }
    //u???????????¬?????¨???????????????
    void splay(node* u){
        while(!(u->isRoot())){
            node* p = u->par;
            node* gp = p->par;
            if(!(p->isRoot())){
                gp->push();
            }
            p->push();
            u->push();
            if(!(p->isRoot())){
                //zig-zig, zig-zag
                rotate((u == p->left) == (p == gp->left) ? p : u);
            }
            rotate(u);
        }
        u->push();
    }
    node* expose(node* u){
        node* last = nullptr;
        for(node* v = u; v; v=v->par){
            splay(v);
            v->left = last;
            updateSize(v);
            last = v;
        }
        splay(u);
        return last;
    }
    //??????u?????¨????????¨???????????????(????????¬?????¨)???????????????
    void evert(node* u){
        expose(u);
        u->rev = !(u->rev);
    }
public:
    node** arr;
    LinkCutTree(){}
    void build(int node_size){
        arr = new node* [node_size];
        for(int i = 0; i < node_size; i++){
            arr[i] = new node(i);
        }
    }
    int TreeSize(node* u){
        evert(u);
        return getSize(u);
    }
    int TreeSize(int unum){ return TreeSize(arr[unum]); }
    node* findRoot(node *u){
        expose(u);
        while(u->right){
            u = u->right;
        }
        splay(u);
        return u;
    }
    node* findRoot(int unum){ return findRoot(arr[unum]); }
    bool connected(node* u,node* v){
        if(u == v){
            return true;
        }
        expose(u);
        expose(v);
        return u->par;
    }
    bool connected(int unum,int vnum){ return connected(arr[unum],arr[vnum]); }
    void link(node* u,node* v){
        if(connected(u,v))  return;
        evert(u);
        u->par = v;
    }
    void link(int unum,int vnum){ link(arr[unum],arr[vnum]); }
    void cut(node* u,node* v){
        evert(u);
        expose(v);
        v->right->par = nullptr;
        v->right = nullptr;
    }
    void cut(int unum,int vnum){ cut(arr[unum],arr[vnum]); }
};

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    LinkCutTree lt;
    int n,m;
    cin >> n >> m;
    lt.build(n);
    rep(i,m){
        int u,v,w;
        cin >> u >> v >> w;
        if(u){
            cout << lt.connected(v,w) << "\n";
        }else{
            lt.link(v,w);
        }
    }
    return 0;
}