CodeEff/ECCO huggingface dataset:
# Original solution
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:
            while self.parents[x] >= 0:
                if self.parents[self.parents[x]] >= 0:
                    self.parents[x] = self.parents[self.parents[x]]
                x = self.parents[x]
            return 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()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

import sys
input = sys.stdin.buffer.readline
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.same(u,v):
            print((1))
        else:
            print((0))


# Optimized solution
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:
            st = []
            while self.parents[x] >= 0:
                st.append(x)
                x = self.parents[x]
            for y in st:
                self.parents[y] = x
            return 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 same(self, x, y):
        return self.find(x) == self.find(y)

import sys
input = lambda:sys.stdin.buffer.readline().rstrip()

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:
        print((int(uf.same(u,v))))
    else:
        uf.union(u,v)
# Original solution
def main():
    class UnionFind:
        def __init__(self, N):
            """
            N:要素数
            root:各要素の親要素の番号を格納するリスト.
                ただし, root[x] < 0 ならその頂点が根で-root[x]が木の要素数.
            rank:ランク
            """
            self.N = N
            self.root = [-1] * N
            self.rank = [0] * N

        def find(self, x):
            """頂点xの根を見つける"""
            if self.root[x] < 0:
                return x
            else:
                while self.root[x] >= 0:
                    x = self.root[x]
                return x

        def union(self, x, y):
            """x,yが属する木をunion"""
            # 根を比較する
            # すでに同じ木に属していた場合は何もしない.
            # 違う木に属していた場合はrankを見てくっつける方を決める.
            # rankが同じ時はrankを1増やす
            x = self.find(x)
            y = self.find(y)
            if x == y:
                return
            elif self.rank[x] > self.rank[y]:
                self.root[x] += self.root[y]
                self.root[y] = x
            else:
                self.root[y] += self.root[x]
                self.root[x] = y
                if self.rank[x] == self.rank[y]:
                    self.rank[y] += 1

        def same(self, x, y):
            """xとyが同じグループに属するかどうか"""
            return self.find(x) == self.find(y)

    import sys
    n, q = list(map(int, sys.stdin.buffer.readline().split()))
    uf = UnionFind(n)
    for _ in range(q):
        t, u, v = list(map(int, input().split()))
        if t:
            print((int(uf.same(u, v))))
        else:
            uf.union(u, v)


main()


# Optimized solution
def main():
    class UnionFind:
        def __init__(self, N):
            """
            N:要素数
            root:各要素の親要素の番号を格納するリスト.
                ただし, root[x] < 0 ならその頂点が根で-root[x]が木の要素数.
            rank:ランク
            """
            self.N = N
            self.root = [-1] * N
            self.rank = [0] * N

        def find(self, x):
            """頂点xの根を見つける"""
            if self.root[x] < 0:
                return x
            else:
                while self.root[x] >= 0:
                    x = self.root[x]
                return x

        def union(self, x, y):
            """x,yが属する木をunion"""
            # 根を比較する
            # すでに同じ木に属していた場合は何もしない.
            # 違う木に属していた場合はrankを見てくっつける方を決める.
            # rankが同じ時はrankを1増やす
            x = self.find(x)
            y = self.find(y)
            if x == y:
                return
            elif self.rank[x] > self.rank[y]:
                self.root[x] += self.root[y]
                self.root[y] = x
            else:
                self.root[y] += self.root[x]
                self.root[x] = y
                if self.rank[x] == self.rank[y]:
                    self.rank[y] += 1

        def same(self, x, y):
            """xとyが同じグループに属するかどうか"""
            return self.find(x) == self.find(y)

    import sys
    n, q = list(map(int, sys.stdin.buffer.readline().split()))
    uf = UnionFind(n)
    for _ in range(q):
        t, u, v = list(map(int, sys.stdin.buffer.readline().split()))
        if t:
            print((int(uf.same(u, v))))
        else:
            uf.union(u, v)


main()
# Original solution
import sys
input = sys.stdin.readline


def solve():
    N, q = list(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 = list(map(int, input().split()))
        if t:
            print((int(find(u) == find(v))))
        else:
            union(u, v)


solve()


# Optimized solution
import sys
input = sys.stdin.readline


def solve():
    N, q = list(map(int, input().split()))
    root = [-1] * 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
        if root[x] > root[y]:
            x, y = y, x
        root[x] += root[y]
        root[y] = x

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


solve()
# Original solution
# UnionFind
import sys
def input(): return sys.stdin.readline().rstrip()
sys.setrecursionlimit(10**9)
from dataclasses import *
@dataclass
class UnionFind:
  def __init__(self, n):
    self.n = [-1]*n
    self.r = [0]*n
    self.siz = n

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

  def unite(self, x, y):
    x = self.find_root(x)
    y = self.find_root(y)
    if x == y:
      return
    elif self.r[x] > self.r[y]:
      self.n[x] += self.n[y]
      self.n[y] = x
    else:
      self.n[y] += self.n[x]
      self.n[x] = y
      if self.r[x] == self.r[y]:
        self.r[y] += 1
    self.siz -= 1

  def root_same(self, x, y):
    return self.find_root(x) == self.find_root(y)

  def count(self, x):
    return -self.n[self.find_root(x)]

  def size(self):
    return self.siz

n,q=list(map(int,input().split()))
uf=UnionFind(n)
for _ in range(q):
  t,u,v=list(map(int,input().split()))
  if t==0:
    uf.unite(u,v)
  else:
    print((uf.root_same(u,v)+0))

# Optimized solution
# UnionFind
import sys
def input(): return sys.stdin.readline().rstrip()
sys.setrecursionlimit(1000000)
class UnionFind:
  def __init__(self, n):
    self.n = [-1]*n
    self.r = [0]*n
    self.siz = n

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

  def unite(self, x, y):
    x = self.find_root(x)
    y = self.find_root(y)
    if x == y:
      return
    elif self.r[x] > self.r[y]:
      self.n[x] += self.n[y]
      self.n[y] = x
    else:
      self.n[y] += self.n[x]
      self.n[x] = y
      if self.r[x] == self.r[y]:
        self.r[y] += 1
    self.siz -= 1

  def root_same(self, x, y):
    return self.find_root(x) == self.find_root(y)

  def count(self, x):
    return -self.n[self.find_root(x)]

  def size(self):
    return self.siz

n,q=list(map(int,input().split()))
uf=UnionFind(n)
for _ in range(q):
  t,u,v=list(map(int,input().split()))
  if t==0:
    uf.unite(u,v)
  else:
    print((uf.root_same(u,v)+0))
# Original solution
# UnionFind
import sys
def input(): return sys.stdin.readline().rstrip()
sys.setrecursionlimit(1000000)
class UnionFind:
  def __init__(self, n):
    self.n = [-1]*n
    self.r = [0]*n
    self.siz = n

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

  def unite(self, x, y):
    x = self.find_root(x)
    y = self.find_root(y)
    if x == y:
      return
    elif self.r[x] > self.r[y]:
      self.n[x] += self.n[y]
      self.n[y] = x
    else:
      self.n[y] += self.n[x]
      self.n[x] = y
      if self.r[x] == self.r[y]:
        self.r[y] += 1
    self.siz -= 1

  def root_same(self, x, y):
    return self.find_root(x) == self.find_root(y)

  def count(self, x):
    return -self.n[self.find_root(x)]

  def size(self):
    return self.siz

n,q=list(map(int,input().split()))
uf=UnionFind(n)
for _ in range(q):
  t,u,v=list(map(int,input().split()))
  if t==0:
    uf.unite(u,v)
  else:
    print((uf.root_same(u,v)+0))

# Optimized solution
# UnionFind
import sys
input = lambda: sys.stdin.readline().rstrip()
sys.setrecursionlimit(1000000)
class UnionFind:
  def __init__(self, n):
    self.n = [-1]*n
    self.r = [0]*n
    self.siz = n

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

  def unite(self, x, y):
    x = self.find_root(x)
    y = self.find_root(y)
    if x == y:
      return
    elif self.r[x] > self.r[y]:
      self.n[x] += self.n[y]
      self.n[y] = x
    else:
      self.n[y] += self.n[x]
      self.n[x] = y
      if self.r[x] == self.r[y]:
        self.r[y] += 1
    self.siz -= 1

  def root_same(self, x, y):
    return self.find_root(x) == self.find_root(y)

  def count(self, x):
    return -self.n[self.find_root(x)]

  def size(self):
    return self.siz

n,q=list(map(int,input().split()))
uf=UnionFind(n)
for _ in range(q):
  t,u,v=list(map(int,input().split()))
  if t==0:
    uf.unite(u,v)
  else:
    print((uf.root_same(u,v)+0))
# Original solution
# UnionFind
import sys
input = lambda: sys.stdin.readline().rstrip()
sys.setrecursionlimit(1000000)
class UnionFind:
  def __init__(self, n):
    self.n = [-1]*n
    self.r = [0]*n
    self.siz = n

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

  def unite(self, x, y):
    x = self.find_root(x)
    y = self.find_root(y)
    if x == y:
      return
    elif self.r[x] > self.r[y]:
      self.n[x] += self.n[y]
      self.n[y] = x
    else:
      self.n[y] += self.n[x]
      self.n[x] = y
      if self.r[x] == self.r[y]:
        self.r[y] += 1
    self.siz -= 1

  def root_same(self, x, y):
    return self.find_root(x) == self.find_root(y)

  def count(self, x):
    return -self.n[self.find_root(x)]

  def size(self):
    return self.siz

n,q=list(map(int,input().split()))
uf=UnionFind(n)
for _ in range(q):
  t,u,v=list(map(int,input().split()))
  if t==0:
    uf.unite(u,v)
  else:
    print((uf.root_same(u,v)+0))

# Optimized solution
import sys
input = lambda: sys.stdin.readline().rstrip()

# UnionFind
class UnionFind:
    def __init__(self,n):
        self.n=n
        self.a=[-1]*n
        self.siz=n
    def root_find(self,x):
        if self.a[x]<0:
            return x
        else:
            self.a[x]=self.root_find(self.a[x])
            return self.a[x]
    def unite(self,x,y):
        x=self.root_find(x)
        y=self.root_find(y)
        if x==y:
          return
        elif self.a[x]<self.a[y]:
            self.a[x]+=self.a[y]
            self.a[y]=x
        else:
            self.a[y]+=self.a[x]
            self.a[x]=y
        self.siz-=1
    def root_same(self,x,y):
        return self.root_find(x)==self.root_find(y)

n,q=list(map(int,input().split()))
u=UnionFind(n)
for _ in range(q):
    t,a,b=list(map(int,input().split()))
    if t==0:
        u.unite(a,b)
    else:
        print((u.root_same(a,b)+0))
# Original solution
# verify-helper: PROBLEM https://judge.yosupo.jp/problem/unionfind
import sys

input = sys.stdin.buffer.readline


class UnionFindTree:
    """Disjoint-Set Data Structure

    Union-Find Tree

    complexity:
        - init: O(n)
        - find, unite, same: O(alpha(n))
    """

    def __init__(self, n: int) -> None:
        self.par = list(range(n))  # parent
        self.rank = [0] * n  # depth of tree

    def find(self, x: int) -> int:
        if self.par[x] == x:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]

    def unite(self, x: int, y: int) -> None:
        x, y = self.find(x), self.find(y)
        if x == y:
            return
        if self.rank[x] < self.rank[y]:
            self.par[x] = y
        else:
            self.par[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1

    def is_same(self, x: int, y: int) -> bool:
        return self.find(x) == self.find(y)


def main() -> None:
    N, Q = list(map(int, input().split()))
    uft = UnionFindTree(N)
    for _ in range(Q):
        t, u, v = list(map(int, input().split()))
        if t == 0:
            uft.unite(u, v)
        else:
            print((int(uft.is_same(u, v))))


if __name__ == "__main__":
    main()


# Optimized solution
# verify-helper: PROBLEM https://judge.yosupo.jp/problem/unionfind
import sys

input = sys.stdin.buffer.readline


class UnionFindTree:
    """Disjoint-Set Data Structure

    Union-Find Tree

    complexity:
        - init: O(n)
        - find, unite, same: O(alpha(n))
    """

    def __init__(self, n: int) -> None:
        self.par = list(range(n))  # parent
        self.rank = [0] * n  # depth of tree

    def find(self, x: int) -> int:
        if self.par[x] == x:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]

    def unite(self, x: int, y: int) -> None:
        x, y = self.find(x), self.find(y)
        if x == y:
            return
        if self.rank[x] < self.rank[y]:
            self.par[x] = y
        else:
            self.par[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1

    def is_same(self, x: int, y: int) -> bool:
        return self.find(x) == self.find(y)


def main() -> None:
    N, Q = map(int, input().split())
    uft = UnionFindTree(N)
    ans = []
    for _ in range(Q):
        t, u, v = map(int, input().split())
        if t == 0:
            uft.unite(u, v)
        else:
            ans.append(int(uft.is_same(u, v)))
    print(*ans, sep="\n")


if __name__ == "__main__":
    main()
# Original solution
class dsu:
    def __init__(self, n=0):
        self._n = n
        self.parent_or_size = [-1] * n
    
    def merge(self, a: int, b: int) -> int:
        x = self.leader(a)
        y = self.leader(b)
        if x == y:
            return x
        if self.parent_or_size[x] > self.parent_or_size[y]:
            x, y = y, x
        self.parent_or_size[x] += self.parent_or_size[y]
        self.parent_or_size[y] = x
        return x
    
    def same(self, a: int, b: int) -> bool:
        return self.leader(a) == self.leader(b)
    
    def leader(self, a: int) -> int:
        x = a
        while self.parent_or_size[x] >= 0:
            x = self.parent_or_size[x]
        while a != x:
            self.parent_or_size[a], a = x, self.parent_or_size[a]
        return x
    
    def size(self, a: int) -> int:
        return -self.parent_or_size[self.leader(a)]
    
    def groups(self):
        g = [[] for _ in range(self._n)]
        for i in range(self._n):
            g[self.leader(i)].append(i)
        return list(c for c in g if c)

n, q = list(map(int, input().split()))
d = dsu(n)
for _ in range(q):
    t, u, v = list(map(int, input().split()))
    if t == 0:
        d.merge(u, v)
    else:
        print((int(d.same(u, v))))

# Optimized solution
class dsu:
    def __init__(self, n=0):
        self._n = n
        self.parent_or_size = [-1] * n
    
    def merge(self, a: int, b: int) -> int:
        x = self.leader(a)
        y = self.leader(b)
        if x == y:
            return x
        if self.parent_or_size[x] > self.parent_or_size[y]:
            x, y = y, x
        self.parent_or_size[x] += self.parent_or_size[y]
        self.parent_or_size[y] = x
        return x
    
    def same(self, a: int, b: int) -> bool:
        return self.leader(a) == self.leader(b)
    
    def leader(self, a: int) -> int:
        x = a
        while self.parent_or_size[x] >= 0:
            x = self.parent_or_size[x]
        while a != x:
            self.parent_or_size[a], a = x, self.parent_or_size[a]
        return x
    
    def size(self, a: int) -> int:
        return -self.parent_or_size[self.leader(a)]
    
    def groups(self):
        g = [[] for _ in range(self._n)]
        for i in range(self._n):
            g[self.leader(i)].append(i)
        return list(c for c in g if c)

import sys
input = sys.stdin.readline
n, q = list(map(int, input().split()))
d = dsu(n)
for _ in range(q):
    t, u, v = list(map(int, input().split()))
    if t == 0:
        d.merge(u, v)
    else:
        print((int(d.same(u, v))))
# Original solution
from typing import List


class DSU:
    def __init__(self, n: int) -> None:
        self._n = n
        self.parent_or_size = [-1] * n

    def merge(self, a: int, b: int) -> int:
        assert 0 <= a <= self._n
        assert 0 <= b <= self._n
        x, y = self.leader(a), self.leader(b)
        if x == y:
            return x
        if -self.parent_or_size[x] < -self.parent_or_size[y]:
            x, y = y, x
        self.parent_or_size[x] += self.parent_or_size[y]
        self.parent_or_size[y] = x
        return x

    def same(self, a: int, b: int) -> bool:
        assert 0 <= a <= self._n
        assert 0 <= b <= self._n
        return self.leader(a) == self.leader(b)

    def leader(self, a: int) -> int:
        assert 0 <= a < self._n
        while self.parent_or_size[a] >= 0:
            a = self.parent_or_size[a]
        return a

    def size(self, a: int) -> int:
        assert 0 <= a <= self._n
        return -self.parent_or_size[self.leader(a)]

    def groups(self) -> List[List[int]]:
        leader_buf = [self.leader(i) for i in range(self._n)]
        group_size = [0] * self._n
        for i in leader_buf:
            group_size[i] += 1
        result = [[] for _ in range(self._n)]
        for i in range(self._n):
            result[leader_buf[i]].append(i)
        result = [i for i in result if i]
        return result


n, q = list(map(int, input().split()))
dsu = DSU(n)

for _ in range(q):
    t, u, v = list(map(int, input().split()))
    if t == 0:
        dsu.merge(u, v)
    else:
        print((1 if dsu.same(u, v) else 0))


# Optimized solution
class DSU:
    def __init__(self, n):
        self._n = n
        self.parent_or_size = [-1] * n

    def merge(self, a, b):
        x, y = self.leader(a), self.leader(b)
        if x == y:
            return x
        if -self.parent_or_size[x] < -self.parent_or_size[y]:
            x, y = y, x
        self.parent_or_size[x] += self.parent_or_size[y]
        self.parent_or_size[y] = x
        return x

    def same(self, a, b):
        return self.leader(a) == self.leader(b)

    def leader(self, a):
        while self.parent_or_size[a] >= 0:
            a = self.parent_or_size[a]
        return a

    def size(self, a):
        return -self.parent_or_size[self.leader(a)]

    def groups(self):
        leader_buf = [self.leader(i) for i in range(self._n)]
        group_size = [0] * self._n
        for i in leader_buf:
            group_size[i] += 1
        result = [[] for _ in range(self._n)]
        for i in range(self._n):
            result[leader_buf[i]].append(i)
        result = [i for i in result if i]
        return result


n, q = list(map(int, input().split()))
dsu = DSU(n)

for _ in range(q):
    t, u, v = list(map(int, input().split()))
    if t == 0:
        dsu.merge(u, v)
    else:
        print((1 if dsu.same(u, v) else 0))
# Original solution
class DSU:
    def __init__(self, n):
        self._n = n
        self.parent_or_size = [-1] * n

    def merge(self, a, b):
        x, y = self.leader(a), self.leader(b)
        if x == y:
            return x
        if -self.parent_or_size[x] < -self.parent_or_size[y]:
            x, y = y, x
        self.parent_or_size[x] += self.parent_or_size[y]
        self.parent_or_size[y] = x
        return x

    def same(self, a, b):
        return self.leader(a) == self.leader(b)

    def leader(self, a):
        while self.parent_or_size[a] >= 0:
            a = self.parent_or_size[a]
        return a

    def size(self, a):
        return -self.parent_or_size[self.leader(a)]

    def groups(self):
        leader_buf = [self.leader(i) for i in range(self._n)]
        group_size = [0] * self._n
        for i in leader_buf:
            group_size[i] += 1
        result = [[] for _ in range(self._n)]
        for i in range(self._n):
            result[leader_buf[i]].append(i)
        result = [i for i in result if i]
        return result


n, q = list(map(int, input().split()))
dsu = DSU(n)

for _ in range(q):
    t, u, v = list(map(int, input().split()))
    if t == 0:
        dsu.merge(u, v)
    else:
        print((1 if dsu.same(u, v) else 0))


# Optimized solution
import sys
input = sys.stdin.readline

class DSU:
    def __init__(self, n):
        self._n = n
        self.parent_or_size = [-1] * n

    def merge(self, a, b):
        x, y = self.leader(a), self.leader(b)
        if x == y:
            return x
        if -self.parent_or_size[x] < -self.parent_or_size[y]:
            x, y = y, x
        self.parent_or_size[x] += self.parent_or_size[y]
        self.parent_or_size[y] = x
        return x

    def same(self, a, b):
        return self.leader(a) == self.leader(b)

    def leader(self, a):
        while self.parent_or_size[a] >= 0:
            a = self.parent_or_size[a]
        return a

    def size(self, a):
        return -self.parent_or_size[self.leader(a)]

    def groups(self):
        leader_buf = [self.leader(i) for i in range(self._n)]
        group_size = [0] * self._n
        for i in leader_buf:
            group_size[i] += 1
        result = [[] for _ in range(self._n)]
        for i in range(self._n):
            result[leader_buf[i]].append(i)
        result = [i for i in result if i]
        return result


n, q = list(map(int, input().split()))
dsu = DSU(n)

for _ in range(q):
    t, u, v = list(map(int, input().split()))
    if t == 0:
        dsu.merge(u, v)
    else:
        print((1 if dsu.same(u, v) else 0))