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: Accepted)

using System;
using System.Linq;//リストの使用
using System.Collections.Generic;
using System.Text;//テキストの高速出力に必要
class Program
{
static string[] input = Console.ReadLine().Split(' ');
static int n = int.Parse(input[0]);
static int q = int.Parse(input[1]);
static int[] unionfind = new int[n];//親

	static void Main()
	{  
    for(int i = 0; i < n; i++)
    {
      unionfind[i] = -1;//初期化
    }
    
    for(long i = 0; i < q; i++)
    {
      int[] numsa = Array.ConvertAll(Console.ReadLine().Split(' '),int.Parse);
      
      if(numsa[0] == 0) UnionFindUnite(numsa[1],numsa[2]);//結合
      else
      {
        if(UnionFindFind(numsa[1]) == UnionFindFind(numsa[2])) Console.WriteLine(1);
        else Console.WriteLine(0);
      }
    }
	}

  static void UnionFindUnite(int x, int y)
  {//unionfindで頂点x,yをO(log頂点数)で結合
    x = UnionFindFind(x);
    y = UnionFindFind(y);
    if(x == y) return;

    if(unionfind[x] > unionfind[y])
    {
      int swapMemo = unionfind[x];
      unionfind[x] = unionfind[y];
      unionfind[y] = swapMemo;
    }
    unionfind[x] += unionfind[y];
    unionfind[y] = x;
  }

  static int UnionFindFind(int x)
  {//unionfindで頂点xが属する集合をO(log頂点数)で返す
    if(unionfind[x] < 0) return x;
    return (unionfind[x] = UnionFindFind(unionfind[x]));
  }

  static int UnionFindSize(int x)
  {//unionfindで頂点xが属する集合の大きさをO(log頂点数)で返す
    return (-unionfind[UnionFindFind(x)]);
  }

  static int[] UnionFindSizes()
  {//unionfindで各集合の大きさをO(頂点数 *log頂点数)で返す
  //例えば{1,2,5,2}なら{1,2,1}(順不同)を返す
    int[] answers;
    int answerCount = 1;
    int answerCountSub = 0;
    int n = unionfind.Length;
    int[] parents = new int[n];
    for(int i = 0; i < n; i++)
    {
      parents[i] = UnionFindFind(i);
    }
    Array.Sort(parents);

    for(int i = 1; i < n; i++)
    {
      if(parents[i-1] != parents[i]) answerCount++;
    }
    answers = new int[answerCount];
    answers[0]++;

    for(int i = 1; i < n; i++)
    {
      if(parents[i-1] != parents[i])
      {
        answerCountSub++;
      }
      answers[answerCountSub]++;
    }
    
    return answers;
  }
  
}