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 C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;

class MainClass
{
    static void Main()
    {
        var NM = Console.ReadLine().Split().Select(int.Parse).ToArray();
        int N = NM[0], M = NM[1];
        var G = new Graph<(int,long)>(N);
        for (int i = 0; i < M; i++)
        {
            var r = Console.ReadLine().Split().Select(_=>int.Parse(_)-1).ToArray();
            G.Add(r[0], (r[1],1L));
        }
        var ST = Console.ReadLine().Split().Select(_=>int.Parse(_)-1).ToArray();
        int S = ST[0], T = ST[1];

        var d = Dijkstra(G, S);

        if (d[T] == long.MaxValue) Console.WriteLine(-1);
        else Console.WriteLine(d[T]/3);
    }

    static long[] Dijkstra(Graph<(int to, long cost)> G, int sp)
    {
        //sp からスタート
        var d = new long[3][];
        for (int i = 0; i < 3; i++)
        {
            d[i] = Enumerable.Repeat(long.MaxValue, G.Length).ToArray();
        }
        d[0][sp] = 0;
        var que = new PriorityQueue<(int to, long cost,int times)>(500000, (x, y) => x.cost.CompareTo(y.cost));
        que.Push((sp, 0,0));
        while (que.Size > 0)
        {
            var p = que.Pop();
            int v = p.to;
            int t = p.times;
            int nt = (t + 1) % 3;
            //if (d[t][v] < p.cost) continue;
            foreach (var i in G[v])
            {
                if (d[nt][i.to] > d[t][v] + i.cost)
                {
                    d[nt][i.to] = d[t][v] + i.cost;
                    que.Push((i.to, d[nt][i.to],nt));
                }
            }
        }
        return d[0];
    }
}
class Graph<T>
{
    private List<T>[] G;
    public Graph(int size)
    {
        G = new List<T>[size];
        for (int i = 0; i < size; i++)
        {
            G[i] = new List<T>();
        }
    }

    public List<T> this[int i] => G[i];
    public void Add(int from, T to) => G[from].Add(to);
    public List<T>[] ToListArray() => G;
    public int Length => G.Length;
}
public class PriorityQueue<T>
{
    public long Size { get; private set; } = 0;
    public long MaxSize { get; private set; } = 0;
    public T[] m_heap;
    private Comparison<T> Comp = null;

    public PriorityQueue(long maxSize, Comparison<T> comp)
    {
        if (maxSize <= 0)
            throw new Exception();
        MaxSize = maxSize;
        m_heap = new T[maxSize];

        Comp = comp;
    }

    public void Push(T x)
    {
        if (Size == MaxSize)
        {
            T[] new_heap = new T[MaxSize << 1];
            Array.Copy(m_heap, new_heap, MaxSize);
            m_heap = new_heap;
            MaxSize <<= 1;
        }

        long i = Size++;
        while (i > 0)
        {
            long p = (i - 1) / 2;
            if (Comp(m_heap[p], x) <= 0)
                break;
            m_heap[i] = m_heap[p];
            i = p;
        }
        m_heap[i] = x;
    }

    public T Pop()
    {
        if (Size == 0)
            throw new Exception("Queue is empty.");

        T result = m_heap[0];
        T x = m_heap[--Size];
        long i = 0;
        while (i * 2 + 1 < Size)
        {
            long c1 = i * 2 + 1, c2 = i * 2 + 2;
            if (c2 < Size && Comp(m_heap[c2], m_heap[c1]) < 0)
                c1 = c2;
            if (Comp(m_heap[c1], x) >= 0)
                break;
            m_heap[i] = m_heap[c1];
            i = c1;
        }
        m_heap[i] = x;

        return result;
    }
}