結果

問題 No.763 Noelちゃんと木遊び
ユーザー hytkxdhytkxd
提出日時 2024-05-09 22:14:54
言語 Ruby
(3.3.0)
結果
TLE  
実行時間 -
コード長 2,773 bytes
コンパイル時間 402 ms
コンパイル使用メモリ 7,680 KB
実行使用メモリ 102,084 KB
最終ジャッジ日時 2024-05-09 22:15:03
合計ジャッジ時間 7,142 ms
ジャッジサーバーID
(参考情報)
judge1 / judge3
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 TLE -
testcase_01 -- -
testcase_02 -- -
testcase_03 -- -
testcase_04 -- -
testcase_05 -- -
testcase_06 -- -
testcase_07 -- -
testcase_08 -- -
testcase_09 -- -
testcase_10 -- -
testcase_11 -- -
testcase_12 -- -
testcase_13 -- -
testcase_14 -- -
testcase_15 -- -
testcase_16 -- -
testcase_17 -- -
testcase_18 -- -
testcase_19 -- -
testcase_20 -- -
権限があれば一括ダウンロードができます
コンパイルメッセージ
Syntax OK

ソースコード

diff #

#!/usr/local/bin/ruby
class BipartiteMatching
  LEFT,RIGHT=0,1
  def initialize(n,adj,left=nil,right=nil)
    @n,@adj,@left,@right = n,adj,left,right # adj is assumed bipartite.
    @matching_num,@match = nil,nil
  end
  private
  def bipartite
    unless @left
      part = Array.new(2){[]}
      visited = []
      (0...@n).each do |i|
        unless visited[i]
          que = [i]
          visited[i] = LEFT
          part[LEFT].push(i)
          until que.empty?
            v = que.shift
            d1 = visited[v]+1
            @adj[v].each do |w|
              unless visited[w]
                visited[w] = d1
                part[d1%2].push(w)
                que.push(w)
              end
            end
          end
        end
      end
      @left,@right = part
    end
  end
  def altpath(v)
    # return true if alternating path starting from v to be augmented.
    bool = false
    @visited[v] = true
    @adj[v].each do |u|
      w = @match[u]
      if w.nil? || (@visited[w].nil? && altpath(w))
        bool,@match[v],@match[u] = true,u,v
        break
      end
    end
    bool
  end
  public
  def matching
    #kuhn algorithm:
    # Start by unsaturated vertex, find an augmenting path, update the matching.
    # return number of max matching, and the matching list.
    unless @match
      r = 0
      @match = Array.new(@n)
      (0...@n).each do |i|
      unless @match[i]
        @visited = Array.new(@n)
        if altpath(i)
          r+=1
        end
      end
      end
      @matching_num = r
    end
    [@matching_num,@match]
  end
  def min_vertex_cover
    # https://en.wikipedia.org/wiki/K%C5%91nig's_theorem_(graph_theory)
    matching
    bipartite
    @visited = Array.new(@n)
    @cover = Array.new(@n)
    @left.each{@cover[_1]=true}
    @left.each do |i|
      unless @visited[i] || @match[i]
        altcover(i)
      end
    end
    (0...@n).filter_map{_1 if @cover[_1]}
  end
  def altcover(v)
    # v is in A.
    # push to @cover when v is in A but not in altpath, or when v is in B and altpath.
    unless @visited[v]
      @visited[v] = true
      @cover[v] = false
      @adj[v].each do |u|
        unless @visited[u]
          @cover[u] = true
          altcover(@match[u])
        end
      end
    end
  end
end
### END: class BipartiteMatching

class PlayWithNoel
  def initialize(*arg)
    @n,@uv, = arg
  end

  private
  def graph
    @adj=Array.new(@n){Array.new}
    @uv.each{|u,v| @adj[u-1].push(v-1); @adj[v-1].push(u-1)}
  end

  public

  def ans
    graph
    tree = BipartiteMatching.new(@n,@adj)
    cover = tree.min_vertex_cover
    @n-cover.size
  end
end
### END: class PlayWithNoel
iod = STDIN
n = iod.gets.to_i
uv = Array.new(n-1){iod.gets.split.map &:to_i}
puts PlayWithNoel.new(n,uv).ans
exit 0
0