🌳

[ABC287 C] Path Graph?

2024/03/01に公開

https://atcoder.jp/contests/abc287/tasks/abc287_c

パスグラフか判定する問題。

前提知識

次数とは?

節から出ている辺の数のこと。

パスグラフとは?

  • 無駄がない (閉路がない)
    • 辺の数 = 節の数 - 1
  • 次数がすべて 2 以下
    • 上のグラフで言えば A=1 B=2 C=1 なので正しい
  • 連結している
    • 森の中に木の数が1つ

コード (AC)

N, M = gets.split.collect(&:to_i)                    # => [4, 3]
XY = M.times.collect { gets.split.collect(&:to_i) }  # => [[1, 3], [4, 2], [3, 2]]
ds = DisjointSet.new(1..N).unites(XY)
valid = [
  M = N - 1,
  XY.flatten.tally.all? { |_, c| c <= 2 },
  ds.tree_count == 1,
].all?
valid                                                # => true
puts valid ? "Yes" : "No"

DisjointSet クラスで判定を吸収する

SOLID の S こと単一責任の原則から言えば賛否ありそうだが、入力する辺をすべて保持しておけば内部で判定が行えて便利ではある。

DisjointSet.prepend Module.new {
  def initialize(...)
    @edges = []
    super
  end

  def unite(x, y)
    @edges << [x, y]
    super
  end

  def path_graph?
    v = true
    v &&= @edges.size == @parents.size.pred
    v &&= @edges.flatten.tally.all? { |_, c| c <= 2 }
    v &&= tree_count == 1
  end
}
N, M = gets.split.collect(&:to_i)                    # => [4, 3]
XY = M.times.collect { gets.split.collect(&:to_i) }  # => [[1, 3], [4, 2], [3, 2]]
ans = DisjointSet.new(1..N).unites(XY).path_graph?   # => true
puts ans ? "Yes" : "No"

参考

Discussion