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# (judge verdict: Time Limit Exceeded)

using System;
using System.Linq;
using System.Collections.Generic;

namespace Miscelleneous {

   class Program {
      public static int cin() { return int.Parse(Console.ReadLine()); }
      public static int[] cins() {
         string[] ss = Console.ReadLine().Split(' ');
         int[] Res = new int[ss.Length];
         for (int i = 0; i<ss.Length; i++) Res[i]=int.Parse(ss[i]);
         return Res;
      }
      public static void print(object s) { Console.WriteLine(s.ToString()); }

      static void Main(string[] args) {
         var I = cins();
         int n = I[0], q = I[1];
         int[] layer = new int[n];
         for (int i = 0; i<n; i++) {
            layer[i]=i;
         }
         List<int>[] H = new List<int>[n];
         Queue<int> G=new Queue<int>();
         HashSet<int> A = new HashSet<int>();
         for (int i = 0; i<n; i++) H[i]=new List<int>();
         for (int m = 0; m<q; m++) {
            I=cins();
            switch (I[0]) {
               case 0:
                  H[I[1]].Add(I[2]);
                  H[I[2]].Add(I[1]);
               break;
               case 1:
                  G.Enqueue(I[1]);
                  A.Add(I[1]);
                  while (G.Count()!=0) {
                     foreach (int j in H[G.Dequeue()]) {
                        if (j==I[2]) { print(1); goto PG; }
                        if (A.Contains(j)) continue;
                        G.Enqueue(j);
                        A.Add(j);
                     }
                  }
               print(0);
               break;
            }
            PG:
               G.Clear();
               A.Clear();
         }
      }
   }
}