Problem:
Problem D: Graph Construction

n 匹のうさぎがいて, 0 番からn − 1 番の番号がついた小屋に1 匹ずつ住んでいる.

あるとき, 秘密の組織によって地下通路の建設工事が行われる, という情報がうさぎたちのもとへ入った. 地下通路を使えば, うさぎたちは他のうさぎたちの小屋へ遊びに行けるようになって嬉しい.

通路は両方向に進むことができ, また通路同士は交わらない. 諸事情により, 一度建設された通路が破壊されてしまうこともある. 通路の建設や破壊の工事は1 本ずつ行われ, 各工事中はうさぎは自分の小屋に留まっているものとする.

うさぎたちは, 工事のいくつかの段階において, あるうさぎとあるうさぎが遊べるかどうかを事前に知りたい. うさぎたちは仲良しなので, 遊びに行くときに他のうさぎの小屋を自由に通ることができる. プログラミングが好きなうさぎたちは, 昔似たような問題を解いたので簡単だろうと思って挑戦し出したが, なかなか効率の良いプログラムが書けない. うさぎの代わりにこの問題を解け.

Input

入力の一行目にはn とk がスペース区切りで与えられる。2 ≤ n ≤ 40 000, 1 ≤ k ≤ 40 000

つづくk 行には工事情報と質問が合わせて, 時間順に与えられる.

“1 u v” — 小屋u とv を結ぶ通路が建設される. 小屋u とv を結ぶ通路がないときにのみ現れる.

“2 u v” — 小屋u とv を結ぶ通路が破壊される. 小屋u とv を結ぶ通路があるときにのみ現れる.

“3 u v” — 小屋u とv のうさぎが遊べるかどうか判定せよ.

0 ≤ u < v < n

Output

入力に現れる各質問について, 遊べるなら”YES”を, そうでないなら”NO”を1 行ずつ出力せよ.

Sample Input 1

4 10
1 0 1
1 0 2
3 1 2
2 0 1
1 2 3
3 0 1
1 0 1
2 0 2
1 1 3
3 0 2

Sample Output 1

YES
NO
YES

Solution in Ruby (judge verdict: Time Limit Exceeded)

module SimpleUndirectedGraphic
    require 'set'

    def reachable?(u, v)
        reached = false
        dfs(u, {:WHEN_VISIT => -> x { reached = true if x == v } })
        reached
    end

    def each_connected_component(&block)
        return enum_for(__method__) unless block_given?
        reached = Set.new
        each_node do |s|
            next if reached.include?(s)
            cc = Set[s]
            queue = [s]
            until queue.empty?
                u = queue.shift
                each_neighbour(u) do |v|
                    next if cc.include?(v)
                    cc << v
                    queue << v
                end
            end
            block.call(cc)
            reached += cc
        end
    end

    def connected_components
        each_connected_component.to_a
    end

    def dfs(root, callback = Hash.new())
        known = Set[
            :WHEN_VISIT,
            :WHEN_CHECK,
            :WHEN_MOVE,
            :WHEN_RETURN,
            :WHEN_LEAVE,
        ]
        callback.keys.each do |name|
            raise "unknown callback: #{name}" if ! known.include?(name)
        end

        f = nil
        f.call(root) if f = callback[:WHEN_VISIT]
        stack = [[root, to_enum(:each_neighbour, root)]]
        parent = { root => root }
        until stack.empty?
            u, itr = stack[-1]
            begin
                v = itr.next
                f.call(u, v) if f = callback[:WHEN_CHECK]
                next if v == parent[u]|| parent[v]

                stack << [v, to_enum(:each_neighbour, v)]
                parent[v] = u
                f.call(u, v) if f = callback[:WHEN_MOVE]

                f.call(v) if f = callback[:WHEN_VISIT]
            rescue StopIteration
                stack.pop
                f.call(u) if f = callback[:WHEN_LEAVE]
                if ! stack.empty?
                    f.call(stack[-1][0], u) if f = callback[:WHEN_RETURN]
                end
            end
        end
    end
end

class Hash
    include SimpleUndirectedGraphic
    alias each_node each_key
    def each_neighbour(u)
        self[u].each do |v|
            yield(v)
        end
    end
end

n, Q = gets.split.map(&:to_i)
U = Math.sqrt(Q).ceil

g0 = {}
(0..n-1).each do |u|
    g0[u] = Set.new
end

(Q / U.to_f).ceil.times do
    g = Marshal.load(Marshal.dump(g0))
    query = []
    U.times do
        query << gets.split.map(&:to_i) rescue break
    end

    target = []
    query.each do |q, u, v|
        if q != 3
            target << [u, v]
        end
    end

    save = Set.new
    target.each do |u, v|
        if g[u].include?(v)
            save << [u, v]
            g[u].delete(v)
            g[v].delete(u)
        end
    end

    conv = {}
    g.each_connected_component do |cc|
        rep = nil
        cc.each do |u|
            rep ||= u
            conv[u] = rep
        end
    end

    save.each do |u, v|
        g[u] << v
        g[v] << u
    end

    g2 = {}
    conv.each_value {|u| g2[u] = Set.new}
    g.each do |u, s|
        s.each do |v|
            x, y = conv[u], conv[v]
            next if x == y
            g2[x] << y
            g2[y] << x
        end
    end

    query.each do |q, u, v|
        x, y = conv[u], conv[v]
        if q == 1
            g0[u] << v
            g0[v] << u
            g2[x] << y
            g2[y] << x
        elsif q == 2
            g0[u].delete(v)
            g0[v].delete(u)
            g2[x].delete(y)
            g2[y].delete(x)
        else
            if x == y
                puts 'YES'
            elsif
                puts g2.reachable?(u, v) ? 'YES' : 'NO'
            end
        end
    end
end