#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <string>
#include <cstring>
#include <chrono>
#include <random>
#include <bitset>
using namespace std;

#define MOD 1000000007
#define PI 3.1415926535897932384626433832795
#define INF (int)1e9

#define vi vector<int>
#define vl vector<ll>
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
#define pll pair<ll, ll>
#define fi first
#define se second
#define szz(x) (int)(x).size()
#define rep(i,l,r) for(int i=l;i<(r);++i)

template <typename A, typename B>
string to_string(pair<A, B> p);
 
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p);
 
template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p);
 
string to_string(const string& s) {
  return '"' + s + '"';
}
 
string to_string(const char* s) {
  return to_string((string) s);
}
 
string to_string(bool b) {
  return (b ? "true" : "false");
}
 
string to_string(vector<bool> v) {
  bool first = true;
  string res = "{";
  for (int i = 0; i < static_cast<int>(v.size()); i++) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(v[i]);
  }
  res += "}";
  return res;
}
 
template <size_t N>
string to_string(bitset<N> v) {
  string res = "";
  for (size_t i = 0; i < N; i++) {
    res += static_cast<char>('0' + v[i]);
  }
  return res;
}
 
template <typename A>
string to_string(A v) {
  bool first = true;
  string res = "{";
  for (const auto &x : v) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(x);
  }
  res += "}";
  return res;
}
 
template <typename A, typename B>
string to_string(pair<A, B> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}
 
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";
}
 
template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p) {
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")";
}
 
void debug_out() { cerr << endl; }
 
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  cerr << " " << to_string(H);
  debug_out(T...);
}
 
#ifdef LOCAL // compile with -DLOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

typedef long long int ll;

int find(int i, vi& parents) {
  if(i == parents[i] || -1 == parents[i]) {
    return i;
  }

  int res = find(parents[i], parents);

  parents[i] = res;

  return res;
}

void unite(int x, int y, vi& parents, vi& ranks) {
  int parent_x = find(x, parents);
  int parent_y = find(y, parents);

  if (ranks[parent_x] > ranks[parent_y]) {
    parents[parent_y] = parent_x;
  } else if (ranks[parent_y] > ranks[parent_x]) {
    parents[parent_x] = parent_y;
  } else {
    parents[parent_x] = parent_y;
    ranks[parent_y]++;
  }
}

int main() {
    // g++ -Wall -Wextra -O2 -std=c++17 -DLOCAL starter.cpp
    ios::sync_with_stdio(false);
    cin.tie(0);

    int n, q;

    cin >> n >> q;

    vi parents(n, -1);
    vi ranks(n, 0);

    while (q --> 0) {
      int command, x, y;

      cin >> command >> x >> y;

      if(command == 0) {
        unite(x, y, parents, ranks);
      }

      if(command == 1) {
        if(find(x, parents) == find(y, parents)) {
          cout << 1 << endl;
        } else {
          cout << 0 << endl;
        }
      }
    }

    return 0;
}


Measured memory_bytes: 3280