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<bits/stdc++.h>
using namespace std;
using ll = long long;

template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }

#define FOR(i,a,b) for(ll i=(a);i<(b);++i)
#define ALL(v) (v).begin(), (v).end()
#define p(s) cout<<(s)<<endl
#define p2(s, t) cout << (s) << " " << (t) << endl
#define br() p("")
#define pn(s) cout << (#s) << " " << (s) << endl
#define p_yes() p("Yes")
#define p_no() p("No")

const ll mod = 1e9 + 7;
const ll inf = 1e18;

void vprint(vector<ll> A){
    ll L = A.size();
    FOR(i, 0, L){
        if(i) cout << ' ';
        cout << A[i];
    }
    cout << endl;
}

const int N_MAX = 100010;
 
struct Edge{
    ll to;
    ll cost;
    Edge(ll to, ll cost): to(to), cost(cost) {}
    Edge(){
        to = 0;
        cost = 0;
    }
    bool operator<(const Edge &another) const
    {
        return to < another.to;
        // return 100000 * to + cost < 100000 * another.to + another.cost;
        // return true;
    }
    bool operator>(const Edge &another) const
    {
        return to > another.to;
        // return 100000 * to + cost < 100000 * another.to + another.cost;
        // return true;
    }
};
 
struct Node{
    ll distance;
    ll index;
    Node(ll d, ll i){
        distance = d;
        index = i;
    }
    Node(){}
 
    bool operator<(const Node &another) const
    {
        return distance < another.distance;
    }
    bool operator>(const Node &another) const
    {
        return distance > another.distance;
    }
};
vector<vector<ll> > G;
bool done[N_MAX];

set<ll> buffer;
void clear_buffer(){
    buffer.clear();
}

void dfs(ll i, ll prev, ll count){
    // cout << "dfs " << i << ' ' << prev << ' ' << count << endl;
    // cout << "dfs" << endl;
    // for(ll to : G[i]){
    //     pn(to);
    // }
    // exit(0);
    // pn(i);
    for(ll to : G[i]){

        // if(i==4){
        //     pn(to);
        // }

        // pn(to);
        // if(to==prev) continue;

        if(count==2){
            // cout << "regi " << to << endl;
            buffer.insert(to);
        }else{
            dfs(to, i, count+1);
        }
    }
}

struct Dijkstra{
    vector<ll> d;
    vector<set<Edge> > graph;
    vector<bool> done;

    // ノード数を入れる
    void initialize(ll size){
        d.resize(size);
        done.resize(size);
        graph.resize(size);
        reset();
    }

    void reset(){
        ll N = graph.size();
        FOR(i, 0, N){
            d[i] = inf;
            done[i] = false;
        }
    }
    
    ll distance(int i){
        if(d.size()<=i) return -1;
        return d[i];
    }

    void print_graph(){
        FOR(i, 0, graph.size()){
            cout << i << " -> ";

            for(auto edge : graph[i]){
                cout << edge.to << " ";
            }
            cout << endl;
        }
        p("distance");
        FOR(i, 0, graph.size()){
            ll d = distance(i);
            cout << i << " " << d << endl;
        }
    }

    void register_edge(ll a, ll b, ll cost){
        // pn("regi");
        // cout << a << ' ' << b << ' ' << cost << endl;
        auto edge = Edge(b, cost);
        graph[a].insert(edge);
        // graph[a].push_back(edge);
    }

    void calc_shortest_path(ll from=0){
        priority_queue<Node, vector<Node>, greater<Node> > que;
        auto node = Node();
        // 始点
        node.index = from;
        node.distance = 0;
        que.push(node);

        while(!que.empty()){
            // 1番distanceが小さいノード
            Node n = que.top();
            que.pop();

            if(done[n.index]){
                continue;
            }
            
            done[n.index] = true;
            d[n.index] = n.distance;

            auto edge_list = graph[n.index];
            // pn(edge_list.size());
            for(auto edge : edge_list){   
                // 短くなるノードがあれば
                if(!done[edge.to] && n.distance + edge.cost < d[edge.to]){
                    ll shorter_distance = n.distance + edge.cost;
                    que.push(Node(shorter_distance, edge.to));
                }
            }
        }
    }
};


int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);

    // input
    ll N, M;
    cin >> N >> M;

    G.resize(N);

    auto dij = Dijkstra();
    dij.initialize(N);

    FOR(i, 0, M){
        ll u, v;
        cin >> u >> v;
        u--;
        v--;
        G[u].push_back(v);
    }

    ll S, T;
    cin >> S >> T;
    S--;
    T--;

    // dfs(0, -1, 0);
    // return 0;

    FOR(i, 0, N){
        clear_buffer();
        dfs(i, -1, 0);
        
        // pn(i);
        // p("buffer");
        // vprint(buffer);
        // for(ll to : buffer){
        //     pn(to);
        // }
        
        for(ll to : buffer){
            if(i==to) continue;
            dij.register_edge(i, to, 1);
        }
    }

    dij.calc_shortest_path(S);
    ll ans = dij.distance(T);

    if(ans == inf){
        p(-1);
    }else{
        p(ans);
    }
    
    return 0;
}