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++14 (GCC 5.4.1) (judge verdict: Time Limit Exceeded)

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;

const int INF = 1e+9;

class UnionFind
{
    private:
        std::vector<int> parent;  // parent[x]: x の根の番号
                                  //            x が根の場合はその連結成分の大きさ
        std::vector<int> rank;    // rank[x]  : x が属する木の高さ
        std::size_t sz;           // 連結成分の数

    public:
        // x が親の場合、parent[x] = -(その連結成分の大きさ)
        UnionFind( std::size_t n ): parent(n, -1), rank(n, 0), sz(n) {}

        // x が属する集合の親を返し、x を親に直接繋ぎ直す(経路圧縮)
        int find( int x )
        {
            if( parent[x] < 0 ) return x;
            else return parent[x] = find( parent[x] );
        }

        // x が属する集合と y が属する集合を統合する
        bool unite( int x, int y )
        {
            x = find( x );
            y = find( y );
            if( x == y ) return false;

            // 大きい方(x)に小さい方(y)を繋げる
            if( rank[x] < rank[y] ) std::swap( x, y );

            parent[x] += parent[y];  // x に連結している成分の大きさを更新する
            parent[y] = x;           // y を x に繋ぐ
            if( rank[x] == rank[y] ) rank[x]++;
            sz--;

            return true;
        }

        bool same( int x, int y ) { return find(x) == find(y); }
        std::size_t size()        { return sz; }
        std::size_t size( int x ) { return - parent[find(x)]; }
};

int main()
{
    int N, M;
    cin >> N >> M;
    UnionFind uni(N);
    vector<vector<int>> G(N);
    for( int i = 0; i < M; ++i ){
        int u, v;
        cin >> u >> v;
        --u, --v;
        G[u].push_back(v);
        uni.unite(u,v);
    }
    int S, T;
    cin >> S >> T;
    --S, --T;

    if( !uni.same(S,T) ){
        cout << -1 << endl;
        return 0;
    }

    vector<int> d(N, INF);  // Sからの距離
    d[S] = 0;
    queue<int> q;
    q.push(S);
    while( !q.empty() ){
        int pos = q.front(); q.pop();
        for( auto a: G[pos] ){
            for( auto b: G[a] ){
                for(auto c: G[b] ){
                    if( d[c] == INF ){
                        d[c] = d[pos]+1;
                        q.push(c);
                    }
                }
            }
        }
        if( d[T] != INF ) break;
    }
    if( d[T] == INF ) cout << -1 << endl;
    else cout << d[T] << endl;


    return 0;
}