#ifndef ONLINE_JUDGE #include "header.hpp" #else #include #include #include using cpp_int=boost::multiprecision::cpp_int; #include templateusing cpp_float=boost::multiprecision::number>; templateusing cpp_double=boost::multiprecision::number>; #endif using namespace std; using ll=long long; inline void yn(bool x){if(x){cout<<"Yes"< inline void erase_duplicate(vector& A){sort(A.begin(),A.end());A.erase(unique(A.begin(),A.end()),A.end());} inline ll powll(ll x,ll n){ll r=1;while(n>0){if(n&1){r*=x;};x*=x;n>>=1;};return r;} using namespace std; using ll=long long; // https://ei1333.github.io/luzhiled/snippets/graph/lowlink.html template< typename G > struct LowLink { const G &g; vector< int > used, ord, low; vector< int > articulation; vector< pair< int, int > > bridge; LowLink(const G &g) : g(g) {} int dfs(int idx, int k, int par) { used[idx] = true; ord[idx] = k++; low[idx] = ord[idx]; bool is_articulation = false; int cnt = 0; for(auto &to : g[idx]) { if(!used[to]) { ++cnt; k = dfs(to, k, idx); low[idx] = min(low[idx], low[to]); is_articulation |= ~par && low[to] >= ord[idx]; if(ord[idx] < low[to]) bridge.emplace_back(minmax(idx, (int) to)); } else if(to != par) { low[idx] = min(low[idx], ord[to]); } } is_articulation |= par == -1 && cnt > 1; if(is_articulation) articulation.push_back(idx); return k; } virtual void build() { used.assign(g.size(), 0); ord.assign(g.size(), 0); low.assign(g.size(), 0); int k = 0; for(int i = 0; i < g.size(); i++) { if(!used[i]) k = dfs(i, k, -1); } } }; int main(){ ll N,M; cin>>N>>M; ll start,goal; cin>>start>>goal; start--; goal--; vector> G(N); for(ll i=0;i>u>>v; u--;v--; G[u].push_back(v); G[v].push_back(u); } LowLink LL(G); LL.build(); for(ll i=0;iLL.bridge[i].second){ swap(LL.bridge[i].first, LL.bridge[i].second); } } sort(LL.bridge.begin(),LL.bridge.end()); vector> res(N, {1LL<<60,1LL<<60}); priority_queue,ll>, vector,ll>>, greater,ll>>> pq; res[start]={0,0}; pq.push({{0,0},start}); while(!pq.empty()){ auto [cc,idx]=pq.top(); auto [d,c]=cc; pq.pop(); if(res[idx] key={min(idx,to),max(idx,to)}; ll xx=lower_bound(LL.bridge.begin(),LL.bridge.end(),key)-LL.bridge.begin(); ll cost=(xxres[idx].first+1){ res[to]={res[idx].first+1, res[idx].second+cost}; pq.push({res[to],to}); }else if(res[to].first==res[idx].first && res[to].second>res[idx].second+cost){ res[to].second=res[idx].second+cost; pq.push({res[to],to}); } } } if(res[goal].first==1LL<<60){ cout<<-1<