v, e, s, g = read_line.split.map(&.to_i) s -= 1 g -= 1 graph = Array.new(v) { [] of Int32 } e.times do a, b = read_line.split.map { |v| v.to_i - 1 } graph[a] << b graph[b] << a end _, bridges = lowlink(graph) bs = Array.new(v) { Set(Int32).new } bridges.each do |a, b| bs[a] << b bs[b] << a end prev = Array.new(v, -1) q = [s] prev[s] = s while q.size > 0 && prev[g] == -1 nq = [] of Int32 q.each do |cur| graph[cur].each do |adj| next if prev[adj] != -1 prev[adj] = cur nq << adj end end q = nq end if prev[g] == -1 puts -1 exit end ans = 0 cur = g while cur != s p = prev[cur] if !bs[cur].includes?(p) ans += 1 end cur = p end puts ans def lowlink(g : Array(Array(Int32))) : Tuple(Set(Int32), Array(Tuple(Int32, Int32))) ord = Array.new(g.size, -1) low = Array.new(g.size, g.size) cnt_child = Array.new(g.size, 0) articulations = Set(Int32).new bridges = [] of Tuple(Int32, Int32) dfs = uninitialized Int32, Int32, Int32 -> Int32 dfs = ->(cur : Int32, idx : Int32, prev : Int32) do ord[cur] = idx low[cur] = idx idx += 1 g[cur].each do |adj| next if adj == prev if ord[adj] == -1 idx = dfs.call(adj, idx, cur) cnt_child[cur] += 1 low[cur] = {low[cur], low[adj]}.min if ord[cur] < low[adj] bridges << {cur, adj} end if cur != 0 && ord[cur] <= low[adj] articulations << cur end else low[cur] = {low[cur], ord[adj]}.min end end return idx end dfs.call(0, 0, -1) if cnt_child[0] > 1 articulations << 0 end return articulations, bridges end