Problem:
Score : 500 points

Problem Statement

Ken loves ken-ken-pa (Japanese version of hopscotch). Today, he will play it on a directed graph G.
G consists of N vertices numbered 1 to N, and M edges. The i-th edge points from Vertex u_i to Vertex v_i.

First, Ken stands on Vertex S. He wants to reach Vertex T by repeating ken-ken-pa. In one ken-ken-pa, he does the following exactly three times: follow an edge pointing from the vertex on which he is standing.

Determine if he can reach Vertex T by repeating ken-ken-pa. If the answer is yes, find the minimum number of ken-ken-pa needed to reach Vertex T. Note that visiting Vertex T in the middle of a ken-ken-pa does not count as reaching Vertex T by repeating ken-ken-pa.

Constraints

2 \leq N \leq 10^5

0 \leq M \leq \min(10^5, N (N-1))

1 \leq u_i, v_i \leq N(1 \leq i \leq M)

u_i \neq v_i (1 \leq i \leq M)

If i \neq j, (u_i, v_i) \neq (u_j, v_j).

1 \leq S, T \leq N

S \neq T

Input

Input is given from Standard Input in the following format:

N M
u_1 v_1
:
u_M v_M
S T

Output

If Ken cannot reach Vertex T from Vertex S by repeating ken-ken-pa, print -1.
If he can, print the minimum number of ken-ken-pa needed to reach vertex T.

Sample Input 1

4 4
1 2
2 3
3 4
4 1
1 3

Sample Output 1

2

Ken can reach Vertex 3 from Vertex 1 in two ken-ken-pa, as follows: 1 \rightarrow 2 \rightarrow 3 \rightarrow 4 in the first ken-ken-pa, then 4 \rightarrow 1 \rightarrow 2 \rightarrow 3 in the second ken-ken-pa. This is the minimum number of ken-ken-pa needed.

Sample Input 2

3 3
1 2
2 3
3 1
1 2

Sample Output 2

-1

Any number of ken-ken-pa will bring Ken back to Vertex 1, so he cannot reach Vertex 2, though he can pass through it in the middle of a ken-ken-pa.

Sample Input 3

2 0
1 2

Sample Output 3

-1

Vertex S and Vertex T may be disconnected.

Sample Input 4

6 8
1 2
2 3
3 4
4 5
5 1
1 4
1 5
4 6
1 6

Sample Output 4

2

Solution in Fortran (gfortran v4.8.4) (judge verdict: Time Limit Exceeded)

module mod_t_item
  implicit none
  type :: t_item
    integer :: pos, cost
  end type t_item
  private
  public :: t_item, itemize, compare, swap
contains
  function itemize(pos,cost) result(i)
    implicit none
    integer :: pos, cost
    type(t_item) :: i
    i%pos = pos
    i%cost = cost
    return
  end function itemize
  function compare(i1,i2) result(c)
    implicit none
    type(t_item), intent(in) :: i1, i2
    integer :: c
    c = i1%cost-i2%cost
    return
  end function compare
  subroutine swap(i1,i2)
    implicit none
    type(t_item), intent(inout) :: i1, i2
    type(t_item) :: i
    i = i1
    i1 = i2
    i2 = i
    return
  end subroutine swap
end module mod_t_item
module mod_t_list
  use mod_t_item
  implicit none
  type :: t_list
    integer :: vol
    type(t_item), pointer :: arr(:)
  end type t_list
  private
  public :: t_list, init_list, release_list,push_back
  public :: pop_back, get_at, size_of_list
contains
  subroutine init_list(list)
    implicit none
    type(t_list), intent(inout) :: list
    list%vol = 0
    allocate(list%arr(1))
    return
  end subroutine init_list
  subroutine release_list(list)
    implicit none
    type(t_list), intent(inout) :: list
    if (associated(list%arr)) deallocate(list%arr)
    return
  end subroutine release_list
  subroutine push_back(list,item)
    implicit none
    type(t_list), intent(inout) :: list
    type(t_item), intent(in) :: item
    type(t_item), allocatable :: tmp(:)
    if (size(list%arr).eq.list%vol) then
      allocate(tmp(list%vol))
      tmp = list%arr
      deallocate(list%arr)
      allocate(list%arr(2*list%vol))
      list%arr(1:list%vol) = tmp
      deallocate(tmp)
    end if
    list%vol = list%vol+1
    list%arr(list%vol) = item
    return
  end subroutine push_back
  function pop_back(list) result(item)
    implicit none
    type(t_list), intent(inout) :: list
    type(t_item) :: item
    item = list%arr(list%vol)
    list%vol = list%vol-1
    return
  end function pop_back
  function get_at(list,i) result(item)
    implicit none
    type(t_list), intent(in) :: list
    integer, intent(in) :: i
    type(t_item) :: item
    item = list%arr(i)
    return
  end function get_at
  function size_of_list(list) result(s)
    implicit none
    type(t_list), intent(in) :: list
    integer :: s
    s = list%vol
    return
  end function size_of_list
end module mod_t_list
module mod_t_priority_queue
  use mod_t_item
  use mod_t_list
  implicit none
  type :: t_heap
    type(t_list) :: list
  end type t_heap
  private
  public :: t_heap, init_heap, release_heap, push, pop, size_of_heap
contains
  subroutine init_heap(heap)
    implicit none
    type(t_heap), intent(inout) :: heap
    call init_list(heap%list)
    return
  end subroutine init_heap
  subroutine release_heap(heap)
    implicit none
    type(t_heap), intent(inout) :: heap
    call release_list(heap%list)
    return
  end subroutine release_heap
  subroutine push(heap,item)
    implicit none
    type(t_heap), intent(inout) :: heap
    type(t_item), intent(in) :: item
    integer :: n, i
    call push_back(heap%list,item)
    n = heap%list%vol
    do while (n.gt.1)
      i = n/2
      if (compare(heap%list%arr(n),heap%list%arr(i)).lt.0_8) then
        call swap(heap%list%arr(n),heap%list%arr(i))
      end if
      n = i
    end do
    return
  end subroutine push
  function pop(heap) result(item)
    implicit none
    type(t_heap), intent(inout) :: heap
    type(t_item) :: item, tmp
    integer :: n, i, j
    n = heap%list%vol
    item = heap%list%arr(1)
    heap%list%arr(1) = heap%list%arr(n)
    tmp = pop_back(heap%list)
    i = 1
    do while (2*i.lt.n)
      j = 2*i
      if ((j.lt.n-1).and.(compare(heap%list%arr(j+1),heap%list%arr(j)).lt.0_8)) then
        j = j+1
      end if
      if (compare(heap%list%arr(j),heap%list%arr(i)).lt.0_8) then
        call swap(heap%list%arr(j),heap%list%arr(i))
      end if
      i = j
    end do
    return
  end function pop
  function size_of_heap(heap) result(s)
    implicit none
    type(t_heap), intent(in) :: heap
    integer :: s
    s = size_of_list(heap%list)
    return
  end function size_of_heap
end module mod_t_priority_queue
module mod_t_graph
  use mod_t_item
  use mod_t_list
  use mod_t_priority_queue
  implicit none
  integer, parameter :: infty = 1000000000
  type :: t_graph
    type(t_list), pointer :: edges(:)
  end type t_graph
  private
  public :: infty
  public :: t_graph, init_graph, release_graph, add_edge, add, dijkstra, dfs
contains
  subroutine init_graph(graph,n)
    implicit none
    type(t_graph), intent(inout) :: graph
    integer, intent(in) :: n
    integer :: i
    allocate(graph%edges(n))
    do i = 1, n
      call init_list(graph%edges(i))
    end do
    return
  end subroutine init_graph
  subroutine release_graph(graph)
    implicit none
    type(t_graph), intent(inout) :: graph
    integer :: n, i
    if (.not.associated(graph%edges)) return
    n = size(graph%edges)
    do i = 1, n
      call release_list(graph%edges(i))
    end do
    deallocate(graph%edges)
    return
  end subroutine release_graph
  subroutine add_edge(graph,i,edge)
    implicit none
    type(t_graph), intent(inout) :: graph
    type(t_item), intent(in) :: edge
    integer, intent(in) :: i
    call push_back(graph%edges(i),edge)
    return
  end subroutine add_edge
  subroutine add(graph,i,pos,cost)
    implicit none
    type(t_graph), intent(inout) :: graph
    integer, intent(in) :: i, pos, cost
    call push_back(graph%edges(i),itemize(pos,cost))
    return
  end subroutine add
  function dijkstra(graph,start) result(c)
    implicit none
    type(t_graph), intent(in) :: graph
    integer, intent(in) :: start
    type(t_heap) :: pq
    type(t_item) :: now, next
    integer :: n, i, c(size(graph%edges))
    n = size(graph%edges)
    c = infty
    call init_heap(pq)
    c(start) = 0
    call push(pq,itemize(start,c(start)))
    do while (size_of_heap(pq).gt.0)
      now = pop(pq)
      if (now%cost.gt.c(now%pos)) cycle
      do i = 1, size_of_list(graph%edges(now%pos))
        next = get_at(graph%edges(now%pos),i)
        if (c(next%pos).gt.c(now%pos)+next%cost) then
          c(next%pos) = c(now%pos)+next%cost
          call push(pq,itemize(next%pos,c(next%pos)))
        end if
      end do
    end do
    call release_heap(pq)
    return
  end function dijkstra
  recursive subroutine dfs(graph,newgraph,s,v,c)
    implicit none
    type(t_graph), intent(in) :: graph
    type(t_graph), intent(inout) :: newgraph
    integer, intent(in) :: s, v, c
    type(t_item) :: next
    integer :: i
    if (c.eq.3) then
      call add(newgraph,s,v,1)
      return
    end if
    do i = 1, size_of_list(graph%edges(v))
      next = get_at(graph%edges(v),i)
      call dfs(graph,newgraph,s,next%pos,c+1)
    end do
    return
  end subroutine dfs
end module mod_t_graph
program hopscotch_addict
  use mod_t_graph
  implicit none
  type(t_graph) :: org, kng
  integer :: n, m, u, v, s, t, d(100000), i, k
  d = 0
  read(*,*) n, m
  call init_graph(org,n)
  call init_graph(kng,n)
  do i = 1, m
    read(*,*) u, v
    call add(org,u,v,1)
  end do
  read(*,*) s, t
  do i = 1, n
    call dfs(org,kng,i,i,0)
  end do
  d(1:n) = dijkstra(kng,s)
  if (d(t).eq.infty) then
    write(*,'(i0)') -1
  else
    write(*,'(i0)') d(t)
  end if
  call release_graph(org)
  call release_graph(kng)
  stop
end program hopscotch_addict