# https://www.leighhalliday.com/weighted-quick-union-find-algorithm-in-ruby class UnionFind attr_accessor :nodes, :sizes def initialize(num) self.nodes = [] self.sizes = [] num.times do |n| self.nodes[n] = n self.sizes[n] = 1 end end def root(i) # Loop up the chain until reaching root while nodes[i] != i do # path compression for future lookups nodes[i] = nodes[nodes[i]] i = nodes[i] end i end def union(i, j) rooti = root i rootj = root j # already connected return if rooti == rootj # root smaller to root of larger if sizes[i] < sizes[j] nodes[rooti] = rootj sizes[rootj] += sizes[rooti] else nodes[rootj] = rooti sizes[rooti] += sizes[rootj] end end def connected?(i, j) root(i) == root(j) end end class Mafia < UnionFind def fight(i, j) rooti = root i rootj = root j return if rooti == rootj if sizes[rooti] < sizes[rootj] || sizes[rooti] == sizes[rootj] && rooti > rootj nodes[rooti] = rootj sizes[rootj] += sizes[rooti] else nodes[rootj] = rooti sizes[rooti] += sizes[rootj] end end end N, M = gets.split.map &:to_i apes = Mafia.new(N+1) $<.each{|s| a, b = s.split.map &:to_i apes.fight(a, b) } puts apes.nodes[1..-1].map{|i| apes.root i }