Problem:
Problem J. Prime Routing
Fox Jiro is one of the staffs of the ACM-ICPC 2018 Asia Yokohama Regional Contest and is responsible for designing the network for the venue of the contest. His network consists of $N$ computers, which are connected by $M$ cables. The $i$-th cable connects the $a_i$-th computer and the $b_i$-th computer, and it carries data in both directions. Your team will use the $S$-th computer in the contest, and a judge server is the $T$-th computer.
He decided to adjust the routing algorithm of the network to maximize the performance of the contestants through the magical power of prime numbers. In this algorithm, a packet (a unit of data carried by the network) is sent from your computer to the judge server passing through the cables a prime number of times if possible. If it is impossible, the contestants cannot benefit by the magical power of prime numbers. To accomplish this target, a packet is allowed to pass through the same cable multiple times.
You decided to write a program to calculate the minimum number of times a packet from  $S$ to $T$ needed to pass through the cables. If the number of times a packet passes through the cables cannot be a prime number, print $-1$.
Input
The input consists of a single test case, formatted as follows.
$N$ $M$ $S$ $T$
$a_1$ $b_1$
$\vdots$
$a_M$ $b_M$
The first line consists of four integers $N, M, S,$ and $T$ ($2 \leq N \leq 10^5, 1 \leq M \leq 10^5, 1 \leq S, T \leq N, S \ne T$). The $i$-th line of the following $M$ lines consists of two integers $a_i$ and $b_i$ ($1 \leq a_i < b_i \leq N$), which means the $i$-th cables connects the $a_i$-th computer and the $b_i$-th computer in the network. You can assume that the network satisfies the following conditions.
The network has no multi-edge, i.e.,$(a_i, b_i) \ne (a_j, b_j)$ for all $i,j$ ($1 \leq i < j \leq M$).
The packets from $N$ computers are reachable to $T$ by passing through some number of cables. The number is not necessarily a prime.
Output
If there are ways such that the number of times a packet sent from $S$ to $T$ passes through the cables is a prime number, print the minimum prime number of times in one line. Otherwise, print $-1$.
Examples
Sample Input 1
5 5 1 5
1 2
1 4
2 3
3 4
3 5
Output for Sample Input 1
3
Sample Input 2
5 4 1 5
1 2
2 3
3 4
4 5
Output for Sample Input 2
-1
Sample Input 3
2 1 1 2
1 2
Output for Sample Input 3
3
Sample Input 4
3 3 1 2
1 2
1 3
2 3
Output for Sample Input 4
2

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using a2 = array<ll, 2>;
using a3 = array<ll, 3>;

bool chmin(auto& a, const auto& b) { return a > b ? a = b, 1 : 0; }
bool chmax(auto& a, const auto& b) { return a < b ? a = b, 1 : 0; }

const ll INF = 1e18;
ll mod = 998244353;

ifstream in;
ofstream out;

int main(int argc, char** argv) {
    ios::sync_with_stdio(false);
    cin.tie(0);

    if (argc > 2) {
        in.open(argv[1]);
        cin.rdbuf(in.rdbuf());
        out.open(argv[2]);
        cout.rdbuf(out.rdbuf());
    }

    vector<char> is_prime(2e5, 1);
    is_prime[0] = is_prime[1] = 0;

    for (int i = 2; i < is_prime.size(); i++) {
        if (is_prime[i])
            for (int j = i * 2; j < is_prime.size(); j += i) {
                is_prime[j] = 0;
            }
    }

    ll n, m, s, t;
    cin >> n >> m >> s >> t;
    s--;
    t--;
    vector<vector<ll>> g(n);

    for (int i = 0; i < m; i++) {
        ll a, b;
        cin >> a >> b;
        a--;
        b--;
        g[a].push_back(b);
        g[b].push_back(a);
    }

    vector<a2> dist(n, {INF, INF});
    dist[s][0] = 0;
    queue<a2> que;
    que.push({s, 0});
    while (que.size()) {
        a2 f = que.front();
        que.pop();
        for (auto& x : g[f[0]]) {
            if (chmin(dist[x][f[1] ^ 1], dist[f[0]][f[1]] + 1)) {
                que.push({x, f[1] ^ 1});
            }
        }
    }

    ll ans = INF;
    if (dist[t][0] == 2)
        ans = 2;
    if (dist[t][1] != INF) {
        while (is_prime[dist[t][1]] == 0) {
            dist[t][1] += 2;
        }
        chmin(ans, dist[t][1]);
    }
    cout << (ans == INF ? -1 : ans) << endl;

    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 11040
final_rank: 4

code_snippet: #include<bits/stdc++.h>
// #include<atcoder/all>
// #include<boost/multiprecision/cpp_int.hpp>

using namespace std;
// using namespace atcoder;
// using bint = boost::multiprecision::cpp_int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using vi = vector<ll>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using ve = vector<vector<int>>;
using vb = vector<bool>;
using vvb = vector<vb>;
#define rep(i,s,n) for(ll i = (ll)s;i < (ll)n;i++)
#define rrep(i,l,r) for(ll i = r-1;i >= l;i--)
#define ALL(x) (x).begin(),(x).end()
#define sz(c) ((ll)(c).size())
#define LB(A,x) (int)(lower_bound(A.begin(),A.end(),x)-A.begin())
#define UB(A,x) (int)(upper_bound(A.begin(),A.end(),x)-A.begin())
// #define MOD 1000000007
#define MOD 998244353
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){for(int i = 0;i < v.size();i++)os<<v[i]<<(i+1!=v.size()?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.first<<" "<<p.second;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T> inline bool chmax(T &a,T b){if(a < b){a = b;return true;}return false;}
template<typename T> inline bool chmin(T &a,T b){if(a > b){a = b;return true;}return false;}
ld dist(ld x1,ld y1,ld x2, ld y2){return sqrtl((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}


int main(){
  
  ios_base::sync_with_stdio(0), cin.tie(0);
  int n,m,S,T;cin >> n >> m >> S >> T;
  S--;T--;
  vvi v(n);
  rep(i,0,m){
    int a,b;cin >> a >> b;
    a--;b--;
    v[a].emplace_back(b);
    v[b].emplace_back(a);
  }
  const ll inf = 1ll << 60;
  vvi d(n,vi(2,inf));
  d[S][0] = 0;
  queue<pii> que;
  que.push({S,0});
  while(sz(que)){
    auto [ov,pari] = que.front();que.pop();
    for(auto nv : v[ov]){
      if(d[nv][1-pari] != inf)continue;
      d[nv][1-pari] = d[ov][pari] + 1;
      que.push({nv,1-pari});
    }
  }
  const int MX = 300100;
  vb mem(MX,1);
  mem[0] = mem[1] = 0;
  rep(i,2,MX){
    if(!mem[i])continue;
    for(int j = 2*i;j < MX;j+=i)mem[j] = 0;
  }
  if(d[T][0] == 2){
    cout << 2 << endl;
  }else if(d[T][1] != inf){
    for(int i = d[T][1];i < MX;i += 2){
      if(mem[i]){
        cout << i << endl;break;
      }
    }
  }else cout << -1 << endl;
  

  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 14456
final_rank: 8

code_snippet: #include<bits/stdc++.h>
// #include<atcoder/all>
// #include<boost/multiprecision/cpp_int.hpp>

using namespace std;
// using namespace atcoder;
// using bint = boost::multiprecision::cpp_int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using vi = vector<ll>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using ve = vector<vector<int>>;
using vb = vector<bool>;
using vvb = vector<vb>;
#define rep(i,s,n) for(ll i = (ll)s;i < (ll)n;i++)
#define rrep(i,l,r) for(ll i = r-1;i >= l;i--)
#define ALL(x) (x).begin(),(x).end()
#define sz(c) ((ll)(c).size())
#define LB(A,x) (int)(lower_bound(A.begin(),A.end(),x)-A.begin())
#define UB(A,x) (int)(upper_bound(A.begin(),A.end(),x)-A.begin())
// #define MOD 1000000007
#define MOD 998244353
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){for(int i = 0;i < v.size();i++)os<<v[i]<<(i+1!=v.size()?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.first<<" "<<p.second;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T> inline bool chmax(T &a,T b){if(a < b){a = b;return true;}return false;}
template<typename T> inline bool chmin(T &a,T b){if(a > b){a = b;return true;}return false;}
ld dist(ld x1,ld y1,ld x2, ld y2){return sqrtl((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}


int main(){
  
  ios_base::sync_with_stdio(0), cin.tie(0);
  int n,m,S,T;cin >> n >> m >> S >> T;
  S--;T--;
  vvi v(n);
  rep(i,0,m){
    int a,b;cin >> a >> b;
    a--;b--;
    v[a].emplace_back(b);
    v[b].emplace_back(a);
  }
  const ll inf = 1ll << 60;
  vvi d(n,vi(2,inf));
  d[S][0] = 0;
  queue<pii> que;
  que.push({S,0});
  while(sz(que)){
    auto [ov,pari] = que.front();que.pop();
    for(auto nv : v[ov]){
      if(d[nv][1-pari] != inf)continue;
      d[nv][1-pari] = d[ov][pari] + 1;
      que.push({nv,1-pari});
    }
  }
  const int MX = 100100;
  vb mem(MX,1);
  mem[0] = mem[1] = 0;
  rep(i,2,MX){
    if(!mem[i])continue;
    for(int j = 2*i;j < MX;j+=i)mem[j] = 0;
  }
  if(d[T][0] == 2){
    cout << 2 << endl;
  }else if(d[T][1] != inf){
    for(int i = d[T][1];i < MX;i += 2){
      if(mem[i]){
        cout << i << endl;break;
      }
    }
  }else cout << -1 << endl;
  

  return 0;
}
accuracy: 0.7
time_ms: 30
memory_kb: 14204
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using PLL = pair<ll, ll>;
#define vl vector<ll>
#define rep(i, n) for (ll i = 0; i < n; ++i)
#define loop(i ,m, n) for (ll i = m; i <= n; ++i)
constexpr ll INF = 9009009009009009009LL;

vector<ll> primes(const ll n) {
    vector<bool> is_prime(n + 1, true);
    vector<ll> res;
    is_prime[0] = is_prime[1] = false;
    for (ll i = 2; i <= n; ++i) {
        if (!is_prime[i]) continue;
        if (i != 2) res.push_back(i);
        for (ll j = i * i; j <= n; j += i) is_prime[j] = false;
    }
    return res;
}

int main() {
    ll n, m, s, t; cin >> n >> m >> s >> t;
    --s, --t;
    vector<vector<ll>> g(n, vector<ll>());
    rep(i, m) {
        ll a, b; cin >> a >> b;
        --a, --b;
        g[a].push_back(b);
        g[b].push_back(a);
    }

    vector<vector<ll>> dist(n, vector<ll>(2, INF));
    queue<PLL> q;
    q.push({s, 0});
    dist[s][0] = 0;
    while (!q.empty()) {
        auto [v, c] = q.front();
        q.pop();

        for (const int& nv : g[v]) {
            if (dist[nv][c ^ 1] != INF) continue;
            dist[nv][c ^ 1] = dist[v][c] + 1;
            q.push({nv, c ^ 1});
        }
    }

    if (dist[t][0] == 2) {
        cout << 2 << endl;
        return 0;
    }
    if (dist[t][1] == INF) {
        cout << -1 << endl;
        return 0;
    }

    vector<ll> prime = primes(1e6);
    cout << *lower_bound(prime.begin(), prime.end(), dist[t][1]) << endl;
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 15480
final_rank: 12

code_snippet: #include<bits/stdc++.h>

using namespace std;
#define REPP(i,a,b,c) for(int i=a; i<=b; i+=c)
#define REP(i,a,b) REPP(i,a,b,1)
#define REVV(i,a,b,c) for(int i=a; i>=b; i-=c)
#define REV(i,a,b) REVV(i,a,b,1)
#define FOR(i,a) REP(i,0,(int)a-1)
#define FORD(i,a) REV(i,(int)a-1,0)
#define PB push_back
#define POB pop_back
#define FI first
#define SE second
#define MP make_pair
typedef long long ll;
typedef unsigned long long ull;
typedef pair < int , int > pii;
typedef vector < int > vi;
typedef vector < pii > vii;
typedef vector < ll > vl;
typedef pair < ll , ll > pll;
typedef vector < pll > vll;

const ll MOD = 1e9 + 7;
const double EPS = 1e-9;
const int INF = 1e9;

ll addMod(ll a, ll b){
	if(a + b >= MOD) return a + b - MOD;
	return a + b;
}

ll mulMod(ll a, ll b){
	return (a*b)%MOD;
}

ll fast(ll a, ll b){
	if(b == 0) return 1;
	ll tmp = fast(a,b/2);
	tmp = mulMod(tmp,tmp);
	if(b & 1) tmp = mulMod(tmp,a);
	return tmp;
}

ll GCD(ll a, ll b){
	if(a > b) return GCD(b,a);
	if(a == 0) return b;
	return GCD(b%a,a);
}

//////////////////////////////////////////////

const int N = 1e5;

vi G[N + 5];
int vis[N + 5][3];
int n,m,st,en;
vi pr;
bool flag[3*N + 5];

void gprime(){
	int MX = 3*N;
	REP(i,2,MX){
		if(flag[i]) continue;
		pr.PB(i);
		REP(j,i,MX/i){
			flag[j*i] = true;
		}
	}
}

int find(int v){
	int l = 0, r = pr.size(), mid, ret = -1;
	while(l <= r){
		mid = (l + r) / 2;
		if(pr[mid] >= v){
			r = mid - 1;
			ret = mid;
		}
		else l = mid + 1;
	}
	return ret;
}

int solve(){
	priority_queue < pii > pq;
	pq.push(MP(0,st));
	int now, step, nxt, ret = INF, v;
	while(!pq.empty()){
		now = pq.top().SE;
		step = -pq.top().FI;
		pq.pop();
		if(now == en){
			v = find(step);
			if(v != -1 && (pr[v] - step) % 2 == 0) ret = min(ret,pr[v]);
			else if(v != -1 && (pr[v+1] - step) % 2 == 0) ret = min(ret, pr[v+1]);
			
		}
		if(vis[now][step%2]) continue;
		vis[now][step%2] = true;
		FOR(i,G[now].size()){
			nxt = G[now][i];
			if(!vis[nxt][(step+1)%2]){
				pq.push(MP(-step-1, nxt)); 
			}
		}
	}
	if(ret == INF) ret = -1;
	return ret;
}

int main(){
	ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
	
	gprime();
	
	cin >> n >> m >> st >> en;
	int u,v;
	FOR(i,m){
		cin >> u >> v;
		G[u].PB(v);
		G[v].PB(u);
	}
	
	cout << solve() << endl;
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 10348
final_rank: 6

code_snippet: #include<bits/stdc++.h>

using namespace std;
#define REPP(i,a,b,c) for(int i=a; i<=b; i+=c)
#define REP(i,a,b) REPP(i,a,b,1)
#define REVV(i,a,b,c) for(int i=a; i>=b; i-=c)
#define REV(i,a,b) REVV(i,a,b,1)
#define FOR(i,a) REP(i,0,(int)a-1)
#define FORD(i,a) REV(i,(int)a-1,0)
#define PB push_back
#define POB pop_back
#define FI first
#define SE second
#define MP make_pair
typedef long long ll;
typedef unsigned long long ull;
typedef pair < int , int > pii;
typedef vector < int > vi;
typedef vector < pii > vii;
typedef vector < ll > vl;
typedef pair < ll , ll > pll;
typedef vector < pll > vll;

const ll MOD = 1e9 + 7;
const double EPS = 1e-9;
const int INF = 1e9;

ll addMod(ll a, ll b){
	if(a + b >= MOD) return a + b - MOD;
	return a + b;
}

ll mulMod(ll a, ll b){
	return (a*b)%MOD;
}

ll fast(ll a, ll b){
	if(b == 0) return 1;
	ll tmp = fast(a,b/2);
	tmp = mulMod(tmp,tmp);
	if(b & 1) tmp = mulMod(tmp,a);
	return tmp;
}

ll GCD(ll a, ll b){
	if(a > b) return GCD(b,a);
	if(a == 0) return b;
	return GCD(b%a,a);
}

//////////////////////////////////////////////

const int N = 1e5;

vi G[N + 5];
int vis[N + 5][3];
int n,m,st,en;
vi pr;
bool flag[3*N + 5];

void gprime(){
	int MX = 3*N;
	REP(i,2,MX){
		if(flag[i]) continue;
		pr.PB(i);
		REP(j,i,MX/i){
			flag[j*i] = true;
		}
	}
}

int find(int v){
	int l = 0, r = (int)pr.size()-1, mid, ret = -1;
	while(l <= r){
		mid = (l + r) / 2;
		if(pr[mid] >= v){
			r = mid - 1;
			ret = mid;
		}
		else l = mid + 1;
	}
	return ret;
}

int solve(){
	queue< pii > pq;
	pq.push(MP(0,st));
	int now, step, nxt, ret = INF, v;
	while(!pq.empty()){
		now = pq.front().SE;
		step = pq.front().FI;
		pq.pop();
		if(now == en){
			v = find(step);
			if(v != -1 && (pr[v] - step) % 2 == 0) ret = min(ret,pr[v]);
			else if(v+1 < (int)pr.size() && (pr[v+1] - step) % 2 == 0) ret = min(ret, pr[v+1]);
		}
		if(vis[now][step%2] || step > 3*N) continue;
		vis[now][step%2] = true;
		FOR(i,G[now].size()){
			nxt = G[now][i];
			if(!vis[nxt][(step+1)%2]){
				pq.push(MP((step+1), nxt)); 
			}
		}
	}
	if(ret == INF) ret = -1;
	return ret;
}

int main(){
	ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
	memset(flag,0,sizeof flag);
	memset(vis,0,sizeof vis);
	gprime();
	cin >> n >> m >> st >> en;
	int u,v;
	FOR(i,m){
		cin >> u >> v;
		G[u].PB(v);
		G[v].PB(u);
	}
	
	cout << solve() << endl;
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 10352
final_rank: 3

code_snippet: #include <bits/stdc++.h>
#define sf scanf
#define pf printf
#define pb push_back
using namespace std;

typedef long long LL;

const int N = 1e5;

bool isprime[2*N + 20], visodd[N+10], viseven[N+10];
vector <int> g[N+10];

void sieve(){
	for(LL i = 2 ; i < 200010 ; i++) isprime[i] = 1;
	
	for(LL i = 2 ; i < 200010 ; i++){
		if(isprime[i]){			
			for(LL j = i*i ; j < 200010 ; j += i){
				isprime[j] = false;
			}
		}
	}
}

int main(){
    sieve();
    
    int V, E, T, S, a, b;
    
    sf("%d %d %d %d",&V,&E,&T,&S);
    for(int i=0;i<E;++i){
        sf("%d %d",&a,&b);
        g[a].pb(b);
        g[b].pb(a);
    }
    
    queue <int> q;
    queue <int> step;
    q.push(T);
    step.push(0);
    
    memset(visodd,0,sizeof(visodd));
    memset(viseven,0,sizeof(viseven));
    viseven[T] = 1;
    
    bool odd = 0;
    int ans = -1;
    int st = 0;
    
    int sz,cur;
    while(!q.empty()){
        cur = q.front();
        st = step.front();
        // pf(">>> %d %d\n",cur,st);
        q.pop();
        step.pop();
        
        if(odd && st > 2){
            ans = 3;
            break;
        }
        
        if(cur == S){
            if(st == 1){
                odd = 1;   
            }else if(st == 2){
                ans = 2;
                break;
            }else if(st % 2 == 1){
                while(!isprime[st]){
                    st += 2;
                }
                ans = st;
                break;
            }
            continue;
        }
        
        sz = g[cur].size();
        for(int i=0;i<sz;++i){
            // pf("%d ",g[cur][i]);
            if(st % 2 == 1){
                if(!viseven[g[cur][i]] && g[cur][i] != S){
                    q.push(g[cur][i]);
                    step.push(st+1);
                    viseven[g[cur][i]] = 1;
                }else if(g[cur][i] == S){
                    q.push(g[cur][i]);
                    step.push(st+1);
                }    
            }else{
                if(!visodd[g[cur][i]] && g[cur][i] != S){
                    q.push(g[cur][i]);
                    step.push(st+1);
                    visodd[g[cur][i]] = 1;
                }else if(g[cur][i] == S){
                    q.push(g[cur][i]);
                    step.push(st+1);
                }
            }
        }
        // pf("\n");
    }
    
    if(ans == -1 && odd) ans=3;

    pf("%d\n",ans);
    
	return 0;
}
accuracy: 0.7
time_ms: 20
memory_kb: 9200
final_rank: 14

code_snippet: #include<bits/stdc++.h>

using namespace std;
#define REPP(i,a,b,c) for(int i=a; i<=b; i+=c)
#define REP(i,a,b) REPP(i,a,b,1)
#define REVV(i,a,b,c) for(int i=a; i>=b; i-=c)
#define REV(i,a,b) REVV(i,a,b,1)
#define FOR(i,a) REP(i,0,(int)a-1)
#define FORD(i,a) REV(i,(int)a-1,0)
#define PB push_back
#define POB pop_back
#define FI first
#define SE second
#define MP make_pair
typedef long long ll;
typedef unsigned long long ull;
typedef pair < int , int > pii;
typedef vector < int > vi;
typedef vector < pii > vii;
typedef vector < ll > vl;
typedef pair < ll , ll > pll;
typedef vector < pll > vll;

const ll MOD = 1e9 + 7;
const double EPS = 1e-9;
const int INF = 1e9;

ll addMod(ll a, ll b){
	if(a + b >= MOD) return a + b - MOD;
	return a + b;
}

ll mulMod(ll a, ll b){
	return (a*b)%MOD;
}

ll fast(ll a, ll b){
	if(b == 0) return 1;
	ll tmp = fast(a,b/2);
	tmp = mulMod(tmp,tmp);
	if(b & 1) tmp = mulMod(tmp,a);
	return tmp;
}

ll GCD(ll a, ll b){
	if(a > b) return GCD(b,a);
	if(a == 0) return b;
	return GCD(b%a,a);
}

//////////////////////////////////////////////

const int N = 1e5;

vi G[N + 5];
int vis[N + 5][3];
int n,m,st,en;
vi pr;
bool flag[3*N + 5];

void gprime(){
	int MX = 3*N;
	REP(i,2,MX){
		if(flag[i]) continue;
		pr.PB(i);
		REP(j,i,MX/i){
			flag[j*i] = true;
		}
	}
}

int find(int v){
	int l = 0, r = pr.size(), mid, ret = -1;
	while(l <= r){
		mid = (l + r) / 2;
		if(pr[mid] >= v){
			r = mid - 1;
			ret = mid;
		}
		else l = mid + 1;
	}
	return ret;
}

int solve(){
	priority_queue < pii > pq;
	pq.push(MP(0,st));
	int now, step, nxt, ret = INF, v;
	while(!pq.empty()){
		now = pq.top().SE;
		step = -pq.top().FI;
		pq.pop();
		if(now == en){
			v = find(step);
			if(v != -1 && (pr[v] - step) % 2 == 0) ret = min(ret,pr[v]);
			else if(v != -1 && (pr[v+1] - step) % 2 == 0) ret = min(ret, pr[v+1]);
			continue;
		}
		if(vis[now][step%2]) continue;
		vis[now][step%2] = true;
		FOR(i,G[now].size()){
			nxt = G[now][i];
			if(!vis[nxt][(step+1)%2]){
				pq.push(MP(-step-1, nxt)); 
			}
		}
	}
	if(ret == INF) ret = -1;
	return ret;
}

int main(){
	ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
	
	gprime();
	
	cin >> n >> m >> st >> en;
	int u,v;
	FOR(i,m){
		cin >> u >> v;
		G[u].PB(v);
		G[v].PB(u);
	}
	
	cout << solve() << endl;
	return 0;
}
accuracy: 0.7
time_ms: 30
memory_kb: 10480
final_rank: 16

code_snippet: #include <iostream>
#include <iomanip>
#include <cassert>
#include <vector>
#include <algorithm>
#include <utility>
#include <numeric>
#include <tuple>
#include <ranges>
namespace ranges = std::ranges;
namespace views = std::views;
// #include "Src/Number/IntegerDivision.hpp"
// #include "Src/Utility/BinarySearch.hpp"
// #include "Src/Sequence/CompressedSequence.hpp"
// #include "Src/Sequence/RunLengthEncoding.hpp"
// #include "Src/Algebra/Group/AdditiveGroup.hpp"
// #include "Src/DataStructure/FenwickTree/FenwickTree.hpp"
// #include "Src/DataStructure/SegmentTree/SegmentTree.hpp"
// using namespace zawa;
// #include "atcoder/modint"
// using mint = atcoder::modint998244353;
int N, M, S, T;
std::vector<int> g[100010];
bool prime(int v) {
    if (v == 1) return false;
    for (int i = 2 ; i * i <= v ; i++) if (v % i == 0) return false;
    return true;
}
int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    std::cin >> N >> M >> S >> T;
    S--; T--;
    for (int i = 0 ; i < M ; i++) {
        int u, v;
        std::cin >> u >> v;
        u--; v--;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    std::vector dist(2, std::vector<int>(N, -1));
    dist[0][S] = 0;
    std::vector<std::pair<int, int>> que;
    que.push_back({0, S});
    for (int t = 0 ; t < std::ssize(que) ; t++) {
        const auto [p, v] = que[t];
        for (int x : g[v]) if (dist[p^1][x] == -1) {
            dist[p^1][x] = dist[p][v] + 1;
            que.push_back({p^1, x});
        }
    }
    if (dist[0][T] == 2) {
        std::cout << 2 << '\n';
    }
    else if (dist[1][T] == -1) {
        std::cout << -1 << '\n';
    }
    else {
        while (!prime(dist[1][T])) dist[1][T] += 2;
        std::cout << dist[1][T] << '\n';
    }
}
accuracy: 1
time_ms: 20
memory_kb: 13236
final_rank: 5

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

bool isPrime(int X) {
    if (X <= 1) return false;
    rep(i,2,X) {
        if (i*i > X) break;
        if (X % i == 0) return false;
    }
    return true;
}

int main() {
    int N, M, S, T;
    cin >> N >> M >> S >> T;
    S--, T--;
    vector<vector<int>> G(N);
    rep(i,0,M) {
        int A, B;
        cin >> A >> B;
        A--, B--;
        G[A].push_back(B), G[B].push_back(A);
    }
    vector<vector<int>> Dist(N,vector<int>(2,inf));
    Dist[S][0] = 0;
    queue<pair<int,int>> Q;
    Q.push({S,0});
    while(!Q.empty()) {
        auto [P,D] = Q.front();
        Q.pop();
        int ND = D^1;
        for (int NP : G[P]) {
            if (chmin(Dist[NP][ND],Dist[P][D]+1)) {
                Q.push({NP,ND});
            }
        }
    }
    if (Dist[T][0] >= 4 && Dist[T][1] == inf) {
        cout << -1 << endl;
        return 0;
    }
    if (Dist[T][0] == 2) {
        cout << 2 << endl;
        return 0;
    }
    int Cur = Dist[T][1];
    while(1) {
        if (isPrime(Cur)) {
            cout << Cur << endl;
            return 0;
        }
        Cur += 2;
    }
}
accuracy: 1
time_ms: 50
memory_kb: 13824
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

bool is_prime(int n) {
    if (n == 1) return false;
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0)
            return false;
    }
    return true;
}

int main() {
    int n, m, s, t;
    cin >> n >> m >> s >> t;
    s--, t--;
    vector<vector<int> > g(n);
    for (int i = 0; i < m; i++) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        g[a].push_back(b);
        g[b].push_back(a);
    }

    vector<int> dist(n, 1e9);
    dist[s] = 0;
    queue<int> q;
    q.push(s);
    while (!q.empty()) {
        int v = q.front();
        q.pop();

        for (int to = 0; to < g[v].size(); to++) {
            if (dist[g[v][to]] > dist[v] + 1) {
                dist[g[v][to]] = dist[v] + 1;
                q.push(g[v][to]);
            }
        }
    }

    if (is_prime(dist[t])) {
        cout << dist[t] << "\n";
    } else {
        if (dist[t] % 2 == 0 || dist[t] == 1) {
            bool good = false;
            for (int i = 0; i < n; i++) {
                for (int to = 0; to < g[i].size(); to++) {
                    if (dist[i] == dist[g[i][to]] && dist[i] != 1e9)
                        good = true;
                }
            }

            if (!good) {
                if (dist[t] != 1) {
                    cout << "-1\n";
                    return 0;
                }
            } else {
                dist[t]++;
            }
        }

        while (!is_prime(dist[t])) {
            dist[t] += 2;
        }
        cout << dist[t] << "\n";
    }
}
accuracy: 0.35
time_ms: 50
memory_kb: 7988
final_rank: 18

code_snippet: // competitive-verifier: PROBLEM
#ifdef ATCODER
#pragma GCC target("sse4.2,avx512f,avx512dq,avx512ifma,avx512cd,avx512bw,avx512vl,bmi2")
#endif
#pragma GCC optimize("Ofast,fast-math,unroll-all-loops")
#include <bits/stdc++.h>
#ifndef ATCODER
#pragma GCC target("sse4.2,avx2,bmi2")
#endif
template <class T, class U>
constexpr bool chmax(T &a, const U &b) {
    return a < (T)b ? a = (T)b, true : false;
}
template <class T, class U>
constexpr bool chmin(T &a, const U &b) {
    return (T)b < a ? a = (T)b, true : false;
}
constexpr std::int64_t INF = 1000000000000000003;
constexpr int Inf = 1000000003;
constexpr double EPS = 1e-7;
constexpr double PI = 3.14159265358979323846;
#define FOR(i, m, n) for (int i = (m); i < int(n); ++i)
#define FORR(i, m, n) for (int i = (m)-1; i >= int(n); --i)
#define FORL(i, m, n) for (int64_t i = (m); i < int64_t(n); ++i)
#define rep(i, n) FOR (i, 0, n)
#define repn(i, n) FOR (i, 1, n + 1)
#define repr(i, n) FORR (i, n, 0)
#define repnr(i, n) FORR (i, n + 1, 1)
#define all(s) (s).begin(), (s).end()
struct Sonic {
    Sonic() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(20);
    }
    constexpr void operator()() const {}
} sonic;
using namespace std;
using ll = std::int64_t;
using ld = long double;
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
    return is >> p.first >> p.second;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
    for (T &i : v) is >> i;
    return is;
}
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
    return os << '(' << p.first << ',' << p.second << ')';
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    for (auto it = v.begin(); it != v.end(); ++it) os << (it == v.begin() ? "" : " ") << *it;
    return os;
}
template <class Head, class... Tail>
void co(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cout << head << '\n';
    else std::cout << head << ' ', co(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
void ce(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cerr << head << '\n';
    else std::cerr << head << ' ', ce(std::forward<Tail>(tail)...);
}
void Yes(bool is_correct = true) { std::cout << (is_correct ? "Yes\n" : "No\n"); }
void No(bool is_not_correct = true) { Yes(!is_not_correct); }
void YES(bool is_correct = true) { std::cout << (is_correct ? "YES\n" : "NO\n"); }
void NO(bool is_not_correct = true) { YES(!is_not_correct); }
void Takahashi(bool is_correct = true) { std::cout << (is_correct ? "Takahashi" : "Aoki") << '\n'; }
void Aoki(bool is_not_correct = true) { Takahashi(!is_not_correct); }
/**
 * @brief 重み付きグラフ
 *
 * @tparam T 辺の重みの型
 */
template <class T>
struct Graph {
  private:
    struct _edge {
        constexpr _edge() : _from(), _to(), _weight() {}
        constexpr _edge(int from, int to, T weight) : _from(from), _to(to), _weight(weight) {}
        constexpr bool operator<(const _edge &rhs) const { return weight() < rhs.weight(); }
        constexpr bool operator>(const _edge &rhs) const { return rhs < *this; }
        constexpr int from() const { return _from; }
        constexpr int to() const { return _to; }
        constexpr T weight() const { return _weight; }
      private:
        int _from, _to;
        T _weight;
    };
  public:
    using edge_type = typename Graph<T>::_edge;
    Graph() : _size(), edges() {}
    Graph(int v) : _size(v), edges(v) {}
    const auto &operator[](int i) const { return edges[i]; }
    auto &operator[](int i) { return edges[i]; }
    const auto begin() const { return edges.begin(); }
    auto begin() { return edges.begin(); }
    const auto end() const { return edges.end(); }
    auto end() { return edges.end(); }
    constexpr int size() const { return _size; }
    void add_edge(const edge_type &e) { edges[e.from()].emplace_back(e); }
    void add_edge(int from, int to, T weight = T(1)) { edges[from].emplace_back(from, to, weight); }
    void add_edges(int from, int to, T weight = T(1)) {
        edges[from].emplace_back(from, to, weight);
        edges[to].emplace_back(to, from, weight);
    }
    void input_edge(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            T weight;
            std::cin >> from >> to >> weight;
            add_edge(from - base, to - base, weight);
        }
    }
    void input_edges(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            T weight;
            std::cin >> from >> to >> weight;
            add_edges(from - base, to - base, weight);
        }
    }
  private:
    int _size;
    std::vector<std::vector<edge_type>> edges;
};
template <>
struct Graph<void> {
  private:
    struct _edge {
        constexpr _edge() : _from(), _to() {}
        constexpr _edge(int from, int to) : _from(from), _to(to) {}
        constexpr int from() const { return _from; }
        constexpr int to() const { return _to; }
        constexpr int weight() const { return 1; }
        constexpr bool operator<(const _edge &rhs) const { return weight() < rhs.weight(); }
        constexpr bool operator>(const _edge &rhs) const { return rhs < *this; }
      private:
        int _from, _to;
    };
  public:
    using edge_type = typename Graph<void>::_edge;
    Graph() : _size(), edges() {}
    Graph(int v) : _size(v), edges(v) {}
    const auto &operator[](int i) const { return edges[i]; }
    auto &operator[](int i) { return edges[i]; }
    const auto begin() const { return edges.begin(); }
    auto begin() { return edges.begin(); }
    const auto end() const { return edges.end(); }
    auto end() { return edges.end(); }
    constexpr int size() const { return _size; }
    void add_edge(const edge_type &e) { edges[e.from()].emplace_back(e); }
    void add_edge(int from, int to) { edges[from].emplace_back(from, to); }
    void add_edges(int from, int to) {
        edges[from].emplace_back(from, to);
        edges[to].emplace_back(to, from);
    }
    void input_edge(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            std::cin >> from >> to;
            add_edge(from - base, to - base);
        }
    }
    void input_edges(int m, int base = 1) {
        for (int i = 0; i < m; ++i) {
            int from, to;
            std::cin >> from >> to;
            add_edges(from - base, to - base);
        }
    }
  private:
    int _size;
    std::vector<std::vector<edge_type>> edges;
};
/**
 * @brief 素数ライブラリ
 *
 * @tparam N
 */
template <int N = 1 << 22>
struct prime_number {
    prime_number() : is_not_prime(), data() { init(); }
    /**
     * @brief 素数判定
     *
     * @param n
     * @return bool
     */
    bool is_prime(std::int64_t n) const {
        assert(n >= 0);
        if (n < N) return !is_not_prime[n];
        for (auto i : data) {
            if ((std::int64_t)i * i > n) break;
            if (n % i == 0) return false;
        }
        return true;
    }
    std::vector<int> prime_numbers(int x) const {
        std::vector<int> res;
        for (auto i : data) {
            if (i > x) break;
            res.emplace_back(i);
        }
        return res;
    }
    /**
     * @brief 素因数分解
     *
     * @tparam T
     * @param x
     * @return std::vector<std::pair<T, int>>
     */
    template <class T>
    std::vector<std::pair<T, int>> prime_factorization(T x) const {
        if (x == 1) return std::vector<std::pair<T, int>>();
        std::vector<std::pair<T, int>> res;
        for (auto p : data) {
            int cnt = 0;
            for (; x % p == 0; x /= p) ++cnt;
            if (cnt) res.emplace_back(p, cnt);
            if ((std::int64_t)p * p > x) break;
        }
        if (x != 1) res.emplace_back(x, 1);
        return res;
    }
    /**
     * @brief 約数列挙
     *
     * @tparam T
     * @param x
     * @return std::vector<T>
     */
    template <class T>
    std::vector<T> divisors(T x) const {
        if (x == 1) return std::vector<T>(1, 1);
        auto v = prime_factorization(x);
        std::vector<T> res;
        res.emplace_back(1);
        for (auto p : v) {
            int n = res.size();
            res.resize(n * (p.second + 1));
            for (int i = 0; i < n * p.second; ++i) res[n + i] = res[i] * p.first;
            for (int i = 1; i <= p.second; ++i) {
                std::inplace_merge(res.begin(), res.begin() + n * i, res.begin() + n * (i + 1));
            }
        }
        return res;
    }
    /**
     * @brief 因数分解列挙
     *
     * @tparam T
     * @param x
     * @return std::vector<std::vector<T>>
     */
    template <class T>
    std::vector<std::vector<T>> factorization(T x) const {
        std::vector<std::vector<T>> res;
        auto f = [&](auto self, std::vector<T> v, T a) -> void {
            if (a == 1) res.emplace_back(v);
            for (auto i : this->divisors(a)) {
                if (i == 1 || (!v.empty() && v.back() > i)) continue;
                v.emplace_back(i);
                self(self, v, a / i);
                v.pop_back();
            }
        };
        f(f, std::vector<T>(), x);
        return res;
    }
  private:
    std::bitset<N> is_not_prime;
    std::vector<int> data;
    void init() {
        is_not_prime[0] = is_not_prime[1] = true;
        for (int i = 2; i < N; ++i) {
            if (!is_not_prime[i]) {
                data.emplace_back(i);
                if ((std::int64_t)i * i >= N) continue;
                if (i == 2) {
                    for (int j = i * i; j < N; j += i) is_not_prime[j] = true;
                } else {
                    for (int j = i * i; j < N; j += i << 1) is_not_prime[j] = true;
                }
            }
        }
    }
};
prime_number pn;
int main(void)
{
    int n, m, s, t;
    cin >> n >> m >> s >> t;
    --s, --t;
    Graph<void> g(n);
    g.input_edges(m);
    vector dp(n, vector(2, Inf));
    queue<pair<int, int>> que;
    dp[s][0] = 0;
    que.emplace(s, 0);
    while (!que.empty())
    {
        auto [x, y] = que.front();
        que.pop();
        for (auto e : g[x])
        {
            if (chmin(dp[e.to()][!y], dp[x][y] + 1))
            {
                que.emplace(e.to(), !y);
            }
        }
    }
    if (dp[t][0] <= 2)
    {
        co(2);
        return 0;
    }
    int ans = dp[t][1];
    if (ans == Inf)
    {
        co(-1);
        return 0;
    }
    while (true)
    {
        if (pn.is_prime(ans))
        {
            co(ans);
            break;
        }
        ans += 2;
    }
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 15840
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll=long long;
using vll=vector<ll>;
#define rep(i,n) for(ll i=0;i<ll(n);i++)


int main(){
    
    int N,M,S,T;
    cin>>N>>M>>S>>T;
    vector<vector<int>> G(N);
    S--;T--;
    for(int i=0;i<M;i++){
        int a,b;
        cin>>a>>b;
        a--;b--;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    vector<int> D(N*2,1e9);
    D[S]=0;
    queue<int> Q;
    Q.push(S);
    while(!Q.empty()){
        int q=Q.front();
        Q.pop();
        int c=D[q];
        for(int v:G[q%N]){
            if(q>=N){
                if(D[v]>D[q]+1){
                    D[v]=D[q]+1;
                    Q.push(v);
                }
            }
            else{
                if(D[v+N]>D[q]+1){
                    D[v+N]=D[q]+1;
                    Q.push(v+N);
                }
            }
        }
    }
    if(D[T]==2){
        cout<<2<<endl;
    }
    else if(D[T+N]<1e8){
        if(D[T+N]==1)D[T+N]=3;
        while(1){
            bool OK=1;
            for(int j=2;j*j<=D[T+N];j++){
                if(D[T+N]%j==0)OK=0;
            }
            if(OK){
                cout<<D[T+N]<<endl;
                return 0;
            }
            D[T+N]+=2;
        }
    }
    else cout<<-1<<endl;

    
}
accuracy: 1
time_ms: 40
memory_kb: 9408
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll=long long;
using vll=vector<ll>;
#define rep(i,n) for(ll i=0;i<ll(n);i++)


int main(){
    
    int N,M,S,T;
    cin>>N>>M>>S>>T;
    vector<vector<int>> G(N);
    S--;T--;
    for(int i=0;i<M;i++){
        int a,b;
        cin>>a>>b;
        a--;b--;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    vector<int> D(N*2,1e9);
    D[S]=0;
    queue<int> Q;
    Q.push(0);
    while(!Q.empty()){
        int q=Q.front();
        Q.pop();
        int c=D[q];
        for(int v:G[q%N]){
            if(q>=N){
                if(D[v]>D[q]+1){
                    D[v]=D[q]+1;
                    Q.push(v);
                }
            }
            else{
                if(D[v+N]>D[q]+1){
                    D[v+N]=D[q]+1;
                    Q.push(v+N);
                }
            }
        }
    }
    if(D[T]==2){
        cout<<2<<endl;
    }
    else if(D[T+N]<1e8){
        if(D[T+N]==1)D[T+N]=3;
        while(1){
            bool OK=1;
            for(int j=2;j*j<=D[T+N];j++){
                if(D[T+N]%j==0)OK=0;
            }
            if(OK){
                cout<<D[T+N]<<endl;
                return 0;
            }
            D[T+N]+=2;
        }
    }
    else cout<<-1<<endl;

    
}
accuracy: 0.2
time_ms: 20
memory_kb: 6404
final_rank: 19

code_snippet: /* -*- coding: utf-8 -*-
 *
 * 2913.cc: Problem J. Prime Routing
 */

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

/* constant */

const int MAX_N = 100000;
const int MAX_N2 = MAX_N * 2;
const int MAX_P = MAX_N2;

/* typedef */

typedef vector<int> vi;
typedef queue<int> qi;

/* global variables */

bool primes[MAX_P + 1];
vi nbrs[MAX_N];
int ds[MAX_N2];

/* subroutines */

int gen_primes(int maxp, vi &pnums) {
  fill(primes, primes + maxp + 1, true);
  primes[0] = primes[1] = false;

  int p;
  for (p = 2; p * p <= maxp; p++)
    if (primes[p]) {
      pnums.push_back(p);
      for (int q = p * p; q <= maxp; q += p) primes[q] = false;
    }
  for (; p <= maxp; p++)
    if (primes[p]) pnums.push_back(p);
  return (int)pnums.size();
}

/* subroutines */

/* main */

int main() {
  vi pnums;
  gen_primes(MAX_P, pnums);
  
  int n, m, st, gl;
  scanf("%d%d%d%d", &n, &m, &st, &gl);
  st--, gl--;
  int n2 = n * 2;
  
  for (int i = 0; i < m; i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    u--, v--;
    nbrs[u].push_back(v);
    nbrs[v].push_back(u);
  }

  fill(ds, ds + n2, -1);
  ds[st * 2] = 0;

  qi q;
  q.push(st * 2);

  while (! q.empty()) {
    int u = q.front(); q.pop();

    for (auto vv: nbrs[u >> 1]) {
      int v = vv * 2 + ((u & 1) ^ 1);
      if (ds[v] < 0) {
	ds[v] = ds[u] + 1;
	q.push(v);
      }
    }
  }

  if (ds[gl * 2] == 2)
    puts("2");
  else if (ds[gl * 2 + 1] > 0) {
    int d = ds[gl * 2 + 1];
    while (! primes[d]) d += 2;
    printf("%d\n", d);
  }
  else
    puts("-1");

  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 9332
final_rank: 1

code_snippet: #include <stdio.h>
#include <vector>
#include <queue>
using namespace std;

char sieve[103000 * 2];
int vis[103000][2], dist[103000][2];
vector<int> ed[103000];
queue<int> q;

void bfs(int x) {
    int r = 1, y;
    vis[x][0] = 1;
    q.push(x * 2);
    while (q.size()) {
        x = q.front() >> 1;
        y = (q.front() & 1);
        q.pop();
        for (int i : ed[x]) {
            if (vis[i][!y]) continue;
            vis[i][!y] = 1;
            dist[i][!y] = dist[x][y] + 1;
            q.push((i << 1) + (!y));
        }
    }
}

int main(void) {
    int n, m, s, t, u, v, r;
    sieve[0] = 1, sieve[1] = 1;
    for (int i = 2; i < 103000 * 2; i++) {
        if (sieve[i]) continue;
        for (int j = i * 2; j < 103000 * 2; j += i) sieve[j] = 1;
    }
    scanf("%d %d %d %d", &n, &m, &s, &t);
    for (int i = 0; i < m; i++) {
        scanf("%d %d", &u, &v);
        ed[u].push_back(v);
        ed[v].push_back(u);
    }
    bfs(s);
    if (vis[t][0] && dist[t][0] <= 2) printf("2\n");
    else if (vis[t][1]) {
        r = dist[t][1];
        for (int i = r;; i += 2) {
            if (!sieve[i]) {
                printf("%d\n", i);
                break;
            }
        }
    }
    else printf("-1\n");
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 10236
final_rank: 2

code_snippet: #include <stdio.h>
#include <vector>
#include <queue>
using namespace std;

char sieve[103000];
int vis[103000][2], dist[103000][2];
vector<int> ed[103000];
queue<int> q;

void bfs(int x) {
    int r = 1, y;
    vis[x][0] = 1;
    q.push(x * 2);
    while (q.size()) {
        x = q.front() >> 1;
        y = (q.front() & 1);
        q.pop();
        for (int i : ed[x]) {
            if (vis[i][!y]) continue;
            vis[i][!y] = 1;
            dist[i][!y] = dist[x][y] + 1;
            q.push((i << 1) + (!y));
        }
    }
}

int main(void) {
    int n, m, s, t, u, v, r;
    sieve[0] = 1, sieve[1] = 1;
    for (int i = 2; i < 103000; i++) {
        if (sieve[i]) continue;
        for (int j = i * 2; j < 103000; j += i) sieve[j] = 1;
    }
    scanf("%d %d %d %d", &n, &m, &s, &t);
    for (int i = 0; i < m; i++) {
        scanf("%d %d", &u, &v);
        ed[u].push_back(v);
        ed[v].push_back(u);
    }
    bfs(s);
    if (vis[t][0] && dist[t][0] <= 2) printf("2\n");
    else if (vis[t][1]) {
        r = dist[t][1];
        for (int i = r;; i += 2) {
            if (!sieve[i]) {
                printf("%d\n", i);
                break;
            }
        }
    }
    else printf("-1\n");
    return 0;
}
accuracy: 0.7
time_ms: 20
memory_kb: 10204
final_rank: 15

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i = 0; i < (n); i++)
using namespace std;
typedef long long ll;

// g <- pair < v , cost > 
template < class T >
vector< T > dijkstra(vector<vector<pair<int, T>>> &g, int s) {
    T INF = numeric_limits< T >::max();
    vector<T> dist(g.size(), INF);
    priority_queue<pair<T,int>, vector<pair<T,int>>, greater<pair<T,int>>> Q;
    Q.push({dist[s] = T(0), s});
    while(!Q.empty()){
        auto [uc, ui] = Q.top(); Q.pop();
        if(uc != dist[ui]) continue;
        for(auto [vi, vc] : g[ui]) if(dist[vi] > uc + vc) 
            Q.push({dist[vi] = uc + vc, vi});
    }
    return dist;
}

struct Eratosthenes {
    vector<bool> isprime;
    vector<int> primes;
    vector<int> spf; // smallest prime factors
    vector<int> mobius;

    Eratosthenes(int N) : isprime(N + 1, true),
                          spf(N + 1, -1),
                          mobius(N + 1, 1) {
        isprime[1] = false;
        spf[1] = 1;

        for(int p = 2; p <= N; p++){
            if(!isprime[p]) continue;
            primes.push_back(p);
            spf[p] = p;
            mobius[p] = -1;
            for(int q = p * 2; q <= N; q += p){
                isprime[q] = false;
                if(spf[q] == -1) spf[q] = p;
                mobius[q] = ((q / p) % p == 0 ? 0 : -mobius[q]);
            }
        }
    }

    vector<pair<int,int>> factorize(int n) {
        vector<pair<int,int>> res;
        while(n > 1) {
            int p = spf[n], e = 0;
            while(spf[n] == p) n /= p, e++;
            res.push_back({p, e}); // p^e
        }
        return res;
    }

    vector<int> divisors(int n) {
        vector<int> res({1});
        auto pf = factorize(n);
        for(auto p : pf) {
            int s = (int)res.size();
            for(int i = 0; i < s; i++) {
                int v = 1;
                for(int j = 0; j < p.second; j++) {
                    v *= p.first;
                    res.push_back(res[i] * v);
                }
            }
        }
        return res;
    }

    template<class T> void fast_zeta(vector< T > &f) {
        int N = f.size();
        vector<bool> isprime = Eratosthenes(N);
        for(int p = 2; p < N; p++) {
            if(!isprime[p]) continue;
            for(int k = (N - 1) / p; k >= 1; k--) {
                f[k] += f[k * p];
            }
        }
    }

    template<class T> void fast_mobius(vector< T > &F) {
        int N = F.size();
        vector<bool> isprime = Eratosthenes(N);
        for(int p = 2; p < N; p++) {
            if(!isprime[p]) continue;
            for(int k = 1; k * p < N; k++) {
                F[k] -= F[k * p];
            }
        }
    }

    template<class T> vector< T > gcd_convolution(const vector< T > &f, const vector< T > &g) {
        int N = max(f.size(), g.size());
        vector< T > F(N, 0), G(N, 0), H(N);
        for(int i = 0; i < f.size(); i++) F[i] = f[i];
        for(int i = 0; i < g.size(); i++) G[i] = g[i];

        fast_zeta(F);
        fast_zeta(G);

        for(int i = 1; i < N; i++) H[i] = F[i] * G[i];

        fast_mobius(H);
        return H;
    }

    long long fast_euler_phi(int n) {
        auto pf = factorize(n);
        long long res = n;
        for(auto p : pf) {
            res *= p.first - 1;
            res /= p.first;
        }
        return res;
    }
};

int main(){
    cin.tie(0);
    ios::sync_with_stdio(0);
    
    int N,M,S,T; cin >> N >> M >> S >> T; S--; T--;
    vector<vector<pair<int,int>>> G(N + N);
    auto f = [&](int v, int p){ return 2 * v + p; };
    rep(i,M) {
        int a,b; cin >> a >> b; a--; b--;
        G[f(a, 1)].push_back({f(b, 0), 1});
        G[f(a, 0)].push_back({f(b, 1), 1});
        G[f(b, 1)].push_back({f(a, 0), 1});
        G[f(b, 0)].push_back({f(a, 1), 1});
    }

    auto dist = dijkstra(G, f(S, 0));
    int INF = numeric_limits<int>::max(), ans = INF;
    if(dist[f(T, 1)] < INF) {
        int target = dist[f(T, 1)];
        auto ps = Eratosthenes(1010101).primes;
        for(int p : ps) if(p != 2 && target <= p) {
            ans = p;
            break;
        }
    }
    if(dist[f(T, 0)] == 2) ans = 2;

    cout << (ans == INF ? -1 : ans) << endl;
}
accuracy: 1
time_ms: 60
memory_kb: 24132
final_rank: 13

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i = 0; i < (n); i++)
using namespace std;
typedef long long ll;

// g <- pair < v , cost > 
template < class T >
vector< T > dijkstra(vector<vector<pair<int, T>>> &g, int s) {
    T INF = numeric_limits< T >::max();
    vector<T> dist(g.size(), INF);
    priority_queue<pair<T,int>, vector<pair<T,int>>, greater<pair<T,int>>> Q;
    Q.push({dist[s] = T(0), s});
    while(!Q.empty()){
        auto [uc, ui] = Q.top(); Q.pop();
        if(uc != dist[ui]) continue;
        for(auto [vi, vc] : g[ui]) if(dist[vi] > uc + vc) 
            Q.push({dist[vi] = uc + vc, vi});
    }
    return dist;
}

struct Eratosthenes {
    vector<bool> isprime;
    vector<int> primes;
    vector<int> spf; // smallest prime factors
    vector<int> mobius;

    Eratosthenes(int N) : isprime(N + 1, true),
                          spf(N + 1, -1),
                          mobius(N + 1, 1) {
        isprime[1] = false;
        spf[1] = 1;

        for(int p = 2; p <= N; p++){
            if(!isprime[p]) continue;
            primes.push_back(p);
            spf[p] = p;
            mobius[p] = -1;
            for(int q = p * 2; q <= N; q += p){
                isprime[q] = false;
                if(spf[q] == -1) spf[q] = p;
                mobius[q] = ((q / p) % p == 0 ? 0 : -mobius[q]);
            }
        }
    }

    vector<pair<int,int>> factorize(int n) {
        vector<pair<int,int>> res;
        while(n > 1) {
            int p = spf[n], e = 0;
            while(spf[n] == p) n /= p, e++;
            res.push_back({p, e}); // p^e
        }
        return res;
    }

    vector<int> divisors(int n) {
        vector<int> res({1});
        auto pf = factorize(n);
        for(auto p : pf) {
            int s = (int)res.size();
            for(int i = 0; i < s; i++) {
                int v = 1;
                for(int j = 0; j < p.second; j++) {
                    v *= p.first;
                    res.push_back(res[i] * v);
                }
            }
        }
        return res;
    }

    template<class T> void fast_zeta(vector< T > &f) {
        int N = f.size();
        vector<bool> isprime = Eratosthenes(N);
        for(int p = 2; p < N; p++) {
            if(!isprime[p]) continue;
            for(int k = (N - 1) / p; k >= 1; k--) {
                f[k] += f[k * p];
            }
        }
    }

    template<class T> void fast_mobius(vector< T > &F) {
        int N = F.size();
        vector<bool> isprime = Eratosthenes(N);
        for(int p = 2; p < N; p++) {
            if(!isprime[p]) continue;
            for(int k = 1; k * p < N; k++) {
                F[k] -= F[k * p];
            }
        }
    }

    template<class T> vector< T > gcd_convolution(const vector< T > &f, const vector< T > &g) {
        int N = max(f.size(), g.size());
        vector< T > F(N, 0), G(N, 0), H(N);
        for(int i = 0; i < f.size(); i++) F[i] = f[i];
        for(int i = 0; i < g.size(); i++) G[i] = g[i];

        fast_zeta(F);
        fast_zeta(G);

        for(int i = 1; i < N; i++) H[i] = F[i] * G[i];

        fast_mobius(H);
        return H;
    }

    long long fast_euler_phi(int n) {
        auto pf = factorize(n);
        long long res = n;
        for(auto p : pf) {
            res *= p.first - 1;
            res /= p.first;
        }
        return res;
    }
};

int main(){
    cin.tie(0);
    ios::sync_with_stdio(0);
    
    int N,M,S,T; cin >> N >> M >> S >> T; S--; T--;
    vector<vector<pair<int,int>>> G(N + N);
    auto f = [&](int v, int p){ return 2 * v + p; };
    rep(i,M) {
        int a,b; cin >> a >> b; a--; b--;
        G[f(a, 1)].push_back({f(b, 0), 1});
        G[f(a, 0)].push_back({f(b, 1), 1});
        G[f(b, 1)].push_back({f(a, 0), 1});
        G[f(b, 0)].push_back({f(a, 1), 1});
    }

    auto dist = dijkstra(G, S);
    int INF = numeric_limits<int>::max(), ans = INF;
    if(dist[f(T, 1)] < INF) {
        int target = dist[f(T, 1)];
        auto ps = Eratosthenes(1010101).primes;
        for(int p : ps) if(p != 2 && target <= p) {
            ans = p;
            break;
        }
    }
    if(dist[f(T, 0)] == 2) ans = 2;

    cout << (ans == INF ? -1 : ans) << endl;
}
accuracy: 0.2
time_ms: 40
memory_kb: 19880
final_rank: 20

code_snippet: #include<bits/stdc++.h>
#define rep(i,a,...) for(int i = (a)*(strlen(#__VA_ARGS__)!=0);i<(int)(strlen(#__VA_ARGS__)?__VA_ARGS__:(a));++i)
#define per(i,a,...) for(int i = (strlen(#__VA_ARGS__)?__VA_ARGS__:(a))-1;i>=(int)(strlen(#__VA_ARGS__)?(a):0);--i)
#define foreach(i, n) for(auto &i:(n))
#define all(x) (x).begin(), (x).end()
#define bit(x) (1ll << (x))
#define lambda(RES_TYPE, ...) (function<RES_TYPE(__VA_ARGS__)>)[&](__VA_ARGS__) -> RES_TYPE
#define method(FUNC_NAME, RES_TYPE, ...) function<RES_TYPE(__VA_ARGS__)> FUNC_NAME = lambda(RES_TYPE, __VA_ARGS__)
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
//const ll MOD = (ll)1e9+7;
const ll MOD = 998244353;
const int INF = (ll)1e9+7;
const ll INFLL = (ll)1e18;
template<class t>
using vvector = vector<vector<t>>;
template<class t>
using vvvector = vector<vector<vector<t>>>;
template<class t>
using priority_queuer = priority_queue<t, vector<t>, greater<t>>;
template<class t, class u> bool chmax(t &a, u b){if(a<b){a=b;return true;}return false;}
template<class t, class u> bool chmin(t &a, u b){if(a>b){a=b;return true;}return false;}
#ifdef DEBUG
#define debug(x) cout<<"LINE "<<__LINE__<<": "<<#x<<" = "<<x<<endl;
#else
#define debug(x) (void)0
#endif

namespace templates{
    ll modpow(ll x, ll b,ll mod=MOD){
        ll res = 1;
        while(b){
            if(b&1)res = res * x % mod;
            x = x * x % mod;
            b>>=1;
        }
        return res;
    }

    ll modinv(ll x){
        return modpow(x, MOD-2);
    }

    bool was_output = false;

    void print();
    template <class t> void print(const vector<t> &);
    template <class t, class u> void print(const pair<t, u> &);
    template <class t> void print(const t&);
    template <class Head, class... Tail> void print(const Head&, const Tail&...);

    template <class t> void println(const vector<vector<t>>&);
    template <class t> void println(const vector<t>&);
    template <class t> void println(const t&);
    template <class Head, class... Tail> void println(const Head&, const Tail&...);
    void println();
    void newline();

    void print(){
        return;
    }

    template <class t>
    void print(const vector<t>&x){
        for(const t&i:x)print(i);
    }
    template <class t, class u>
    void print(const pair<t,u>&p){
        print(p.first);
        print(p.second);
    }
    template <class t>
    void print(const t&x){
        if(was_output)cout<<" ";
        cout<<x;
        was_output = true;
    }
    template <class Head, class... Tail>
    void print(const Head&head,const Tail&...tail){
        print(head);
        print(tail...);
    }

    template<class t>
    void println(const vector<vector<t>>&x){
        for(vector<t> i:x)println(i);
    }
    template<class t>
    void println(const vector<t>&x){
        for(const t&i:x)print(i);
        println();
    }
    template <class t>
    void println(const t&x){
        print(x);
        println();
    }
    void println(){
        if(was_output){
            cout << endl;
            was_output = false;
        }
    }
    template <class Head, class... Tail>
    void println(const Head&head,const Tail&...tail){
        print(head);
        println(tail...);
    }

    void newline(){
        was_output = true;
        println();
    }

    template<class t>
    istream& operator>>(istream&is, vector<t>&x){
        for(auto &i:x)is >> i;
        return is;
    }

    template<class t, class u>
    istream& operator>>(istream&is, pair<t, u>&x){
        is >> x.first >> x.second;
        return is;
    }

    template<class t>
    ostream& operator<<(ostream&os, vector<t> &v){
        os << "{";
        for(t &i:v){
            os << i << ", ";
        }
        os << "}";
        return os;
    }

    template<class t = long long>
    t in(){
        t res; cin >> res; return res;
    }

    template<class t>
    vector<t> sorted(vector<t> line,function<bool(t,t)> comp=[](t a,t b){return a<b;}){
        sort(line.begin(),line.end(),comp);
        return line;
    }

    template<class t>
    vector<t> reversed(vector<t> line){
        reverse(line.begin(),line.end());
        return line;
    }
    string reversed(string str){
        reverse(str.begin(),str.end());
        return str;
    }

    long long gcd(long long a,long long b){
        while(b){
            a %= b;
            swap(a,b);
        }
        return a;
    }

    long long lcm(long long a,long long b){
        return a / gcd(a,b) * b;
    }

    class output_initializer{
    public:
        output_initializer(){
            ios::sync_with_stdio(false);
            cin.tie(nullptr);
            cout << setprecision(20);
        }
    };output_initializer OUTPUT_INITIALIZER_INSTANCE = output_initializer();
}

using namespace templates;

bool is_prime(int n){
    for(int i=2;i*i<=n;++i){
        if(n%i==0)return false;
    }
    return true;
}

int search(int n){
    for(int i=max(n,3);;i+=2){
        if(is_prime(i))return i;
    }
    exit(1);
}

int func(){
    int n = in();
    int m = in();
    int s = in()-1;
    int t = in()-1;
    vvector<int> edges(n*2);
    rep(i,m){
        int a = in()-1;
        int b = in()-1;
        edges[a].emplace_back(b+n);
        edges[b].emplace_back(a+n);
        edges[a+n].emplace_back(b);
        edges[b+n].emplace_back(a);
    }
    vector<int> fast(n*2,INF);
    priority_queuer<pii> pq;
    fast[s] = 0;
    pq.emplace(0,s);
    while(pq.size()){
        pii d = pq.top();
        pq.pop();
        if(fast[d.second] != d.first)continue;
        foreach(e,edges[d.second]){
            if(chmin(fast[e],d.first+1)){
                pq.emplace(d.first+1,e);
            }
        }
    }
    if(fast[t]==2)return 2;
    if(fast[t+n]==INF)return -1;
    return search(fast[t+n]);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    println(func());
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 14792
final_rank: 9