You are given an undirected graph with N vertices and 0 edges. Process Q queries of the following types:
- "0 u v": Add an edge (u, v).
- "1 u v": Print 1 if u and v are in the same connected component, 0 otherwise.

Constraints:
- 1 ≤ N ≤ 200,000
- 1 ≤ Q ≤ 200,000
- 0 ≤ u_i, v_i < N

Input:
Input is given from Standard Input in the following format:
N Q
t_1 u_1 v_1
t_2 u_2 v_2
...
t_Q u_Q v_Q

Output:
For each query of the latter type, print the answer.

Sample Input 1:
4 7
1 0 1
0 0 1
0 2 3
1 0 1
1 1 2
0 0 2
1 1 3

Sample Output 1:
0
1
0
1

# Buggy version:
class UnionFind:
    __slots__ = ["_data_size", "_roots"]

    def __init__(self, data_size: int) -> None:
        self._data_size = data_size
        self._roots = [-1] * data_size

    def __getitem__(self, x: int) -> int:
        while self._roots[x] >= 0:
            x = self._roots[x]
        return x

    def is_connected(self, x: int, y: int) -> bool:
        return self[x] == self[y]

    def unite(self, x: int, y: int) -> None:
        x, y = self[x], self[y]
        if x == y:
            return
        if self._roots[x] > self._roots[y]:
            x, y = y, x
        self._roots[x] += self._roots[y]
        self._roots[y] = x


import sys

read = sys.stdin.read

N, _, *X = map(int, readline().split())
tree = UnionFind(N)
res = []
for t, u, v in zip(*[iter(X)] * 3):
    if t:
        res.append(int(tree.is_connected(u, v)))
    else:
        tree.unite(u, v)
print("\n".join(map(str, res)))


# Fixed version:
class UnionFind:
    __slots__ = ["_data_size", "_roots"]

    def __init__(self, data_size: int) -> None:
        self._data_size = data_size
        self._roots = [-1] * data_size

    def __getitem__(self, x: int) -> int:
        while self._roots[x] >= 0:
            x = self._roots[x]
        return x

    def is_connected(self, x: int, y: int) -> bool:
        return self[x] == self[y]

    def unite(self, x: int, y: int) -> None:
        x, y = self[x], self[y]
        if x == y:
            return
        if self._roots[x] > self._roots[y]:
            x, y = y, x
        self._roots[x] += self._roots[y]
        self._roots[y] = x


import sys

read = sys.stdin.buffer.read

N, Q, *TUV = map(int, read().split())
tree = UnionFind(N)
res = []
for t, u, v in zip(*[iter(TUV)] * 3):
    if t:
        res.append(int(tree.is_connected(u, v)))
    else:
        tree.unite(u, v)
print("\n".join(map(str, res)))

# Buggy version:
import sys
input = sys.stdin.readline
def find(A,x):
    p = A[x]
    if p == x:
        return x
    a = find(A,p)
    A[x] = a
    return a
 
def union(A, x, y):
#    bx, by = sorted([find(A,x), find(A,y)]) # bx, by = find(A,x), find(A,y)だと無限ループ。
    if find(A,x) > find(A,y):
        bx, by = find(A,y), find(A,x)
    else:
        bx, by = find(A,x), find(A,y)
    A[y] = bx
    A[by] = bx

def main():
    N, Q = map( int, input().split())
    TUV = [ tuple( map( int, input().split())) for _ in range(Q)]
    G = [ i for i in range(N)]
    ANS = []
    for t, u, v in TUV:
        if t == 0:
            union(T,u,v)
        else:
            if find(T,u) == find(T,v):
                ANS.append(1)
            else:
                ANS.append(0)
    print("\n".join( map( str, ANS)))
        
if __name__ == '__main__':
    main()


# Fixed version:
import sys
input = sys.stdin.readline
def find(A,x):
    p = A[x]
    if p == x:
        return x
    a = find(A,p)
    A[x] = a
    return a
 
def union(A, x, y):
#    bx, by = sorted([find(A,x), find(A,y)]) # bx, by = find(A,x), find(A,y)だと無限ループ。
    if find(A,x) > find(A,y):
        bx, by = find(A,y), find(A,x)
    else:
        bx, by = find(A,x), find(A,y)
    A[y] = bx
    A[by] = bx

def main():
    N, Q = map( int, input().split())
    TUV = [ tuple( map( int, input().split())) for _ in range(Q)]
    G = [ i for i in range(N)]
    ANS = []
    for t, u, v in TUV:
        if t == 0:
            union(G,u,v)
        else:
            if find(G,u) == find(G,v):
                ANS.append(1)
            else:
                ANS.append(0)
    print("\n".join( map( str, ANS)))
        
if __name__ == '__main__':
    main()

# Buggy version:
def find(u, tree_root):
    tree_root[u] = u if u == tree_root[u] else find(tree_root[u], tree_root)
    return tree_root[u]

def main():
    n, q = map(int, input().split())
    tree_root = list(range(n))
    for i in range(q):
        t, u, v = map(int, input().split())
        u_root, v_root = find(u, tree_root), find(v, tree_root)
        if t:
            print(1 if u_root == v_root else 0)
        else:
            tree_root[u] = v_root

if __name__ == "__main__":
    main()

# Fixed version:
def find(u, find_root):
    find_root[u] = u if u == find_root[u] else find(find_root[u], find_root)
    return find_root[u]

def main():
    n, q = map(int, input().split())
    find_root = list(range(n))
    for i in range(q):
        t, u, v = map(int, input().split())
        u_root, v_root = find(u, find_root), find(v, find_root)
        if t:
            print(1 if u_root == v_root else 0)
        else:
            find_root[u_root] = v_root

if __name__ == "__main__":
    main()

# Buggy version:
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**8)


class UnionFind():
    def __init__(self, n):
        self.par = [-1] * n

    def root(self, x):
        if self.par[x] < 0:
            return x
        else:
            self.par[x] = self.root(self.par[x])  # contraction
            return self.par[x]

    def unite(self, x, y):
        x, y = self.root(x), self.root(y)
        if x != y:
            if self.par[x] > self.par[y]:  # merge technique
                x, y = y, x
            self.par[x] += self.par[y]
            self.par[y] = x

    def same(self, x, y):
        return self.root(x) == self.root(y)

    def size(self, x):
        return -self.par[self.root(x)]


n, q = map(int, input().split())
uf = UnionFind(n)
for _ in range(q):
    t, u, v = map(int, input().split())
    u -= 1
    v -= 1
    if t == 0:
        # add
        uf.unite(u, v)
    else:
        print(1 if uf.same(u, v) else 0)


# Fixed version:
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**8)


class UnionFind():
    def __init__(self, n):
        self.par = [-1] * n

    def root(self, x):
        if self.par[x] < 0:
            return x
        else:
            self.par[x] = self.root(self.par[x])  # contraction
            return self.par[x]

    def unite(self, x, y):
        x, y = self.root(x), self.root(y)
        if x != y:
            if self.par[x] > self.par[y]:  # merge technique
                x, y = y, x
            self.par[x] += self.par[y]
            self.par[y] = x

    def same(self, x, y):
        return self.root(x) == self.root(y)

    def size(self, x):
        return -self.par[self.root(x)]


n, q = map(int, input().split())
uf = UnionFind(n)
for _ in range(q):
    t, u, v = map(int, input().split())
    if t == 0:
        # add
        uf.unite(u, v)
    else:
        print(1 if uf.same(u, v) else 0)

# Buggy version:

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

      
n, q = list(map(lambda x: int(x), input().split()))
uf = UnionFind(n)
for _ in range(q):
    t, u, v = list(map(lambda x: int(x), input().split()))
#     print(uf.parent_indexes)
    if t == 0:
        uf.union(u, v)
        continue
    print('1') if uf.are_in_the_same_group(u, v) else print('0')

# Fixed version:
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n
 
    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]
 
    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
 
        if x == y:
            return
 
        if self.parents[x] > self.parents[y]:
            x, y = y, x
 
        self.parents[x] += self.parents[y]
        self.parents[y] = x
 
    def size(self, x):
        return -self.parents[self.find(x)]
 
    def same(self, x, y):
        return self.find(x) == self.find(y)
 
    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]
 
    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]
 
    def group_count(self):
        return len(self.roots())
 
    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}
 
      
n, q = list(map(lambda x: int(x), input().split()))
uf = UnionFind(n)
for _ in range(q):
    t, u, v = list(map(lambda x: int(x), input().split()))
#     print(uf.parent_indexes)
    if t == 0:
        uf.union(u, v)
        continue
    print('1') if uf.same(u, v) else print('0')

# Buggy version:
import networkx as nx
def MAP(): return map(int, input().split())
n,q=MAP()
g=nx.utils.UnionFind(range(n))
for _ in range(q):
    t,u,v=MAP()
    if t==0:g.union(u,v)
    else:print(1 if g[u]==g[v] else 0

# Fixed version:
import networkx as nx
def MAP(): return map(int, input().split())
n,q=MAP()
g=nx.utils.UnionFind(range(n))
for _ in range(q):
    t,u,v=MAP()
    if t==0:g.union(u,v)
    else:print(1 if g[u]==g[v] else 0)

# Buggy version:
p=[-1]*8**6
for q in[open(0)][1:]:
 q,*x=map(int,q.split());a,b=sorted(map(f:=lambda x:f(p[x])if~p[x]<0else x,x))
 if q:print(+(a==b))
 elif a<b:p[b]=a

# Fixed version:
p=[-1]*8**6
for q in[*open(0)][1:]:
 q,*x=map(int,q.split());a,b=sorted(map(f:=lambda x:f(p[x])if~p[x]<0else x,x))
 if q:print(+(a==b))
 elif a<b:p[b]=a

# Buggy version:
import sys
input = sys.stdin.readline
N, q = map(int, input().split())
root = [-1] * N
rank = [0] * N


def find(x: int) -> int:
    if root[x] < 0:
        return x
    else:
        while root[x] >= 0:
            x = root[x]
        return x


def union(x: int, y: int) -> int:
    y = find(y)
    if x == y:
        return
    elif rank[x] > rank[y]:
        root[x] += root[y]
        root[y] = x
    else:
        root[y] += root[x]
        root[x] = y
        if rank[x] == rank[y]:
            rank[y] += 1



for i in range(q):
    t, u, v = map(int, input().split())
    if t:
        print(int(find(u) == find(v)))
    else:
        union(u, v)


# Fixed version:
import sys
input = sys.stdin.readline


def solve():
    N, q = map(int, input().split())
    root = [-1] * N
    rank = [0] * N

    def find(x: int) -> int:
        if root[x] < 0:
            return x
        else:
            while root[x] >= 0:
                x = root[x]
            return x

    def union(x: int, y: int):
        x = find(x)
        y = find(y)
        if x == y:
            return
        elif rank[x] > rank[y]:
            root[x] += root[y]
            root[y] = x
        else:
            root[y] += root[x]
            root[x] = y
            if rank[x] == rank[y]:
                rank[y] += 1

    for _ in range(q):
        t, u, v = map(int, input().split())
        if t:
            print(int(find(u) == find(v)))
        else:
            union(u, v)


solve()

# Buggy version:
class UnionFind:
    def __init__(self, size):
        self.par = [-1] * size
        
    def find(self, x):
        if self.par[x] < 0:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]

    def unite(self, x, y):
        x, y = self.find(x), self.find(y)
        if x == y: return False
        if self.par[x] > self.par[y]:
            x, y = y, x
        self.par[x] += self.par[y]
        self.par[y] = x
        return True

    def same(self, x, y):
        return self.find(x) == self.find(y)
    
    def size(self, x):
        return -self.par[self.find(x)]

N, Q = map(int, input().split())
uf = Unionfind(N)
for _ in range(Q):
    t, u, v = map(int, input().split())
    if t == 0:
        uf.unite(u, v)
    else:
        if uf.same(u, v):
            print(1)
        else:
            print(0)

# Fixed version:
class UnionFind:
    def __init__(self, size):
        self.par = [-1] * size
        
    def find(self, x):
        if self.par[x] < 0:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]

    def unite(self, x, y):
        x, y = self.find(x), self.find(y)
        if x == y: return False
        if self.par[x] > self.par[y]:
            x, y = y, x
        self.par[x] += self.par[y]
        self.par[y] = x
        return True

    def same(self, x, y):
        return self.find(x) == self.find(y)
    
    def size(self, x):
        return -self.par[self.find(x)]

N, Q = map(int, input().split())
uf = UnionFind(N)
for _ in range(Q):
    t, u, v = map(int, input().split())
    if t == 0:
        uf.unite(u, v)
    else:
        if uf.same(u, v):
            print(1)
        else:
            print(0)

# Buggy version:
#Union Find

#xの根を求める
def find(x):
    if par[x] < 0:
        return x
    else:
        tank = []
        while par[x] >= 0:
            tank.append(x)
            x = par[x]
        for elt in tank:
            par[elt] = x
        return x
#xとyの属する集合の併合
def unite(x,y):
    x = find(x)
    y = find(y)
    
    if x == y:
        return False
    else:
        #sizeの大きいほうがx
        if par[x] > par[y]:
            x,y = y,x
        par[x] += par[y]
        par[y] = x
        return True

#xとyが同じ集合に属するかの判定
def same(x,y):
    return find(x) == find(y)

#xが属する集合の個数
def size(x):
    return -par[find(x)]


import sys
input = sys.stdin.readline

n,q = map(int,input().split())

#初期化
#根なら-size,子なら親の頂点
par = [-1]*n

for i in range(q):
    t,u,v = map(int,input().split())
    if t == 0:
        unite(u,v)
    elif same(x,y):
        print(1)
    else:
        print(0)

# Fixed version:
#Union Find

#xの根を求める
def find(x):
    if par[x] < 0:
        return x
    else:
        tank = []
        while par[x] >= 0:
            tank.append(x)
            x = par[x]
        for elt in tank:
            par[elt] = x
        return x
#xとyの属する集合の併合
def unite(x,y):
    x = find(x)
    y = find(y)
    
    if x == y:
        return False
    else:
        #sizeの大きいほうがx
        if par[x] > par[y]:
            x,y = y,x
        par[x] += par[y]
        par[y] = x
        return True

#xとyが同じ集合に属するかの判定
def same(x,y):
    return find(x) == find(y)

#xが属する集合の個数
def size(x):
    return -par[find(x)]


import sys
input = sys.stdin.readline

n,q = map(int,input().split())

#初期化
#根なら-size,子なら親の頂点
par = [-1]*n

for i in range(q):
    t,u,v = map(int,input().split())
    if t == 0:
        unite(u,v)
    elif same(u,v):
        print(1)
    else:
        print(0)

# Buggy version:
from networkx.utils.union_find import UnionFind
n,q=map(int,input().split())
a=[[int(i) for i in input().split()] for _ in range(q)]

uf=UnionFind()
for i in range(n):
     uf.union(i,i)
for x in a:
     if x[0]==0:
          uf.union(x[1],x[2])
     else:
          f=x[1]
          while True:
               if f==uf.parents[f]:break
               f=uf.parents[f]
          b=x[2]
          while True:
               if b==uf.parents[b]:break
               b=uf.parents[b]
          print(0 if f==b else 1)

# Fixed version:
from networkx.utils.union_find import UnionFind
n,q=map(int,input().split())
a=[[int(i) for i in input().split()] for _ in range(q)]

uf=UnionFind()
for i in range(n):
     uf.union(i,i)
for x in a:
     if x[0]==0:
          uf.union(x[1],x[2])
     else:
          f=x[1]
          while True:
               if f==uf.parents[f]:break
               f=uf.parents[f]
          b=x[2]
          while True:
               if b==uf.parents[b]:break
               b=uf.parents[b]
          print(1 if f==b else 0)

# Buggy version:
class UnionFind():
    def __init__(self,size):
        self.table = [-1 for _  in range(size)]
        self.member_num = [1 for _ in range(size)]
 
    #representative
    def find(self,x):
        while self.table[x] >= 0:
            x = self.table[x]
        return x

    def union(self,x,y):
        s1 = self.find(x)
        s2 = self.find(y)
        m1=self.member_num[s1]
        m2=self.member_num[s2]
        if s1 != s2:
            if m1 != m2:
                if m1 < m2:
                    self.table[s1] = s2
                    self.member_num[s2]=m1+m2
                    return [m1,m2]
                else:
                    self.table[s2] = s1
                    self.member_num[s1]=m1+m2
                    return [m1,m2]
            else:
                self.table[s1] = -1
                self.table[s2] = s1
                self.member_num[s1] = m1+m2
                return [m1,m2]
        return [0,0]

N,Q = list(map(int,input().split()))

uf = UnionFind(N)

for i in range(Q):
    t,u,v = list(map(int,input().split()))
    if t==0:
        uf.union(u-1,v-1)
    else:
        if uf.find(u-1)==uf.find(v-1):
            print(1)
        else:
            print(0)

# Fixed version:
class UnionFind():
    def __init__(self,size):
        self.table = [-1 for _  in range(size)]
        self.member_num = [1 for _ in range(size)]
 
    #representative
    def find(self,x):
        while self.table[x] >= 0:
            x = self.table[x]
        return x

    def union(self,x,y):
        s1 = self.find(x)
        s2 = self.find(y)
        m1=self.member_num[s1]
        m2=self.member_num[s2]
        if s1 != s2:
            if m1 != m2:
                if m1 < m2:
                    self.table[s1] = s2
                    self.member_num[s2]=m1+m2
                    return [m1,m2]
                else:
                    self.table[s2] = s1
                    self.member_num[s1]=m1+m2
                    return [m1,m2]
            else:
                self.table[s1] = -1
                self.table[s2] = s1
                self.member_num[s1] = m1+m2
                return [m1,m2]
        return [0,0]

N,Q = list(map(int,input().split()))

uf = UnionFind(N)

for i in range(Q):
    t,u,v = list(map(int,input().split()))
    
    if t==0:
        uf.union(u,v)
    else:
        if uf.find(u)==uf.find(v):
            print(1)
        else:
            print(0)