🌳

[ABC304 E] Good Graph

2024/02/28に公開

https://atcoder.jp/contests/abc304/tasks/abc304_e

根に変換して考える問題。

例1で問題文を理解する

グラフ編

このグラフは、

次の経路がないことが保証されている。

その状態を「良いグラフ」と言う。

何かして良いグラフにするのではなく、もともと良いグラフである。

クエリ編

続いて次の辺を繋いでも「良いグラフ」を維持しているか? に答える。

2-5
2-6
5-6
5-4

重要なのは、繋ぐ操作が独立しているということ。順番に連結していくのではない。

解法シミュレーション

繋がっていてはいけない経路を「禁止経路」と呼ぶことにする。そして、辺の節を根に変換する。

禁止経路 根-根
1-5 2-4
2-6 2-6
4-3 2-4

そしてクエリの一つめで考えると、

  • 2-5 を根に変換すると 2-4 になる
  • 2-4 は禁止経路に含まれる
  • ということは、もし 2-5 を繋いでしまうと「根2の木」と「根4の木」が繋がってしまう
    • 2-4 が繋がると禁止経路 1-5 4-3 も繋がる
  • したがって辺 2-5 を繋げてしまうと良いグラフではなくなる = No

クエリの三つめで考えると、

  • 5-6 を根に変換すると 4-6 になる
  • 4-6 は禁止経路に含まれない
  • ということは、5-6 を繋いでも禁止経路は維持されたままである
  • したがって辺 2-5 を繋げても良いグラフのままである = Yes

まとめると、

根-根 禁止経路に含れない?
2-5 2-4 No
2-6 2-6 No
5-6 4-6 Yes
5-4 4-4 Yes

となる。

コード (AC)

N, M = gets.split.collect(&:to_i)                    # => [6, 6]
UV = M.times.collect { gets.split.collect(&:to_i) }  # => [[1, 2], [2, 3], [2, 3], [3, 1], [5, 4], [5, 5]]
K = gets.to_i                                        # => 3
XY = K.times.collect { gets.split.collect(&:to_i) }  # => [[1, 5], [2, 6], [4, 3]]
Q = gets.to_i                                        # => 4
PQ = Q.times.collect { gets.split.collect(&:to_i) }  # => [[2, 5], [2, 6], [5, 6], [5, 4]]

ds = DisjointSet[UV]                                 # => 親:{1=>2, 2=>2, 3=>2, 5=>4, 4=>4} 構図:{2=>[1, 2, 3], 4=>[5, 4]} 節数:{2=>3, 4=>2} 木数:2 高さ:{2=>2, 4=>2}
pair = -> (x, y) { [ds.root(x), ds.root(y)].sort }
ignore = XY.collect { |e| pair[*e] }.to_set          # => #<Set: {[2, 4], [2, 6]}>
ans = PQ.collect { |e| !ignore.include?(pair[*e]) }  # => [false, false, true, true]
puts ans.collect { |e| e ? "Yes" : "No" }

参考

Discussion