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;
using System.Numerics;

class Node<T>
{
    private int Height { get; set; }
    private Node<T> Parent { get; set; }
    private long size;
    public long Size { get { return Find().size; } set { size = value; } }
    public T Item { get; }

    public Node(T item)
    {
        Height = 0;
        Parent = this;
        Item = item;
        Size = 1;
    }

    public Node<T> Find()
    {
        if (Parent == this)
        {
            return this;
        }
        var p = Parent.Find();
        Parent = p;
        return p;
    }

    public static void Unite(Node<T> a, Node<T> b)
    {
        var p = a.Find();
        var q = b.Find();
        if (p.Height < q.Height)
        {
            p.Parent = q;
            q.Height = Math.Max(p.Height + 1, q.Height);
            q.Size += p.Size;
            p.Size = 0;
        }
        else
        {
            q.Parent = p;
            p.Height = Math.Max(q.Height + 1, p.Height);
            p.Size += q.Size;
            q.Size = 0;
        }
    }

    public static bool Same(Node<T> a, Node<T> b)
    {
        return a.Find().Item.Equals(b.Find().Item);
    }
}

class MyClass
{
    public static void Solve()
    {
        var input = Console.ReadLine().Split().Select(int.Parse).ToArray();
        var N = input[0];
        var Q = input[1];
        var uf = new Node<int>[N];
        for (int i = 0; i < N; i++)
        {
            uf[i] = new Node<int>(i);
        }
        for (int i = 0; i < Q; i++)
        {
            input = Console.ReadLine().Split().Select(int.Parse).ToArray();
            var com = input[0];
            var x = input[1];
            var y = input[2];
            if (com == 0)
            {
                Node<int>.Unite(uf[x], uf[y]);
            }
            else
            {
                Console.WriteLine(Node<int>.Same(uf[x], uf[y]) ? 1 : 0);
            }
        }
    }

    public static void Main()
    {
        var sw = new System.IO.StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
        Console.SetOut(sw);
        Solve();
        Console.Out.Flush();
    }
}