import Control.Monad
import Data.List
import qualified Data.Vector.Unboxed as V
import qualified Data.Vector.Unboxed.Mutable as MV

root :: MV.IOVector Int -> Int -> IO Int
root par x = do
    p <- MV.unsafeRead par x
    if p == -1 then return x
    else do
        to <- root par p
        MV.unsafeWrite par x to
        return to

unite :: MV.IOVector Int -> MV.IOVector Int -> Int -> Int -> IO ()
unite par siz x y = do 
    rx <- root par x
    ry <- root par y
    when (rx /= ry) $ do
        sx <- MV.unsafeRead siz x
        sy <- MV.unsafeRead siz y
        if (sx < sy) then do
            MV.unsafeWrite par rx ry
            MV.unsafeWrite siz ry (sx + sy)
        else do
            MV.unsafeWrite par ry rx
            MV.unsafeWrite siz rx (sx + sy)


same :: MV.IOVector Int -> Int -> Int -> IO Bool
same par x y = do
    px <- root par x
    py <- root par y
    return (px == py)

main = do
    [n,q] <- fmap(map read . words) getLine
    par <- MV.replicate(n+1)(-1)
    siz <- MV.replicate(n+1)(1)
    replicateM_ q $ do
        [com,x,y] <- fmap(map read . words) getLine
        if com == 0 then
            unite par siz x y
        else do
            f <- same par x y
            if f then print 1
            else 
                print 0
