#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef pair<ll,ll> ii; typedef vector<ll> vi; typedef vector<ii> vii; typedef vector<vi> vvi; #define x first #define y second #define pb push_back #define eb emplace_back #define rep(i,a,b) for(auto i = (a); i < (b); ++i) #define REP(i,n) rep(i,0,n) #define sz(v) ((int) (v).size()) #define rs resize #define all(v) begin(v), end(v) struct dsu{ dsu() { } vi p; dsu(int n) : p(n,-1){} int find(int i){ return p[i] < 0 ? i : p[i] = find(p[i]); } void unite(int a, int b){ if((a = find(a)) == (b = find(b))) return; if(p[a] > p[b]) swap(a,b); p[a] += p[b]; p[b] = a; } }; ll n; vi vader; vvi buren; vvi kinderen; vi d, snij; vector<set<pair<ll,ii>>> snijset; vi welkset; dsu comp; void maakBFSTree(){ kinderen = vvi(n); vader = vi(n, -1); d = vi(n, 1000000000); d[n-1] = 0; queue<ll> rij; rij.push(n-1); ll nu; while(rij.size() > 0){ nu = rij.front(); rij.pop(); for(ll buur : buren[nu]){ if(d[buur] > d[nu] + 1){ d[buur] = d[nu] + 1; kinderen[nu].pb(buur); rij.push(buur); vader[buur] = nu; } } } } void snijKosten(ll i){ //Bepaal eerst de kinderen for(ll k : kinderen[i]) snijKosten(k); //Maak het simpele anwoord if(kinderen[i].size() == 0){ set<pair<ll,ii>> antw; for(ll buur : buren[i]){ if(buur != vader[i]) antw.emplace(make_pair(d[buur] + d[i],make_pair(i,buur))); } if(i != n - 1){ if(antw.begin() == antw.end()) snij[i] = LLONG_MAX; else snij[i] = (*antw.begin()).x - d[i] + 1; } snijset[i] = antw; welkset[i] = i; return; } //Bepaal waar hij naartoe gaat ll best = -1, nu; for(ll j = 0; j < kinderen[i].size(); j++){ nu = kinderen[i][j]; nu = welkset[nu]; if(best == -1 || snijset[nu].size() > snijset[best].size()) best = nu; } //Verenig de componenten for(ll k : kinderen[i]) comp.unite(i,k); //Voeg de rest toe welkset[i] = best; for(ll j = 0; j < kinderen[i].size(); j++){ nu = kinderen[i][j]; nu = welkset[nu]; if(nu == best) continue; for(pair<ll,ii> p : snijset[nu]) { ll a = p.y.x, b = p.y.y; if (comp.find(a) == comp.find(b)) snijset[best].erase(make_pair(p.x,make_pair(b, a))); else snijset[best].emplace(p); } } //Voeg i toe for(ll buur : buren[i]) { if (buur != vader[i]) { if (comp.find(buur) != comp.find(i)) { snijset[best].emplace(make_pair(d[buur] + d[i],make_pair(i, buur))); } else { snijset[best].erase(make_pair(d[buur] + d[i],make_pair(buur, i))); } } } //Bepaal het antwoord if(i != n - 1){ if(snijset[best].size() == 0) snij[i] = LLONG_MAX; else { snij[i] = (*snijset[best].begin()).x - d[i] + 1; } } } int main(){ ios_base::sync_with_stdio(false); cin.tie(NULL); cout << fixed << setprecision(20); ll m; cin >> n >> m; buren = vvi(n); ll a, b; for(ll i = 0; i < m; i++) { cin >> a >> b; a--; b--; buren[a].pb(b); buren[b].pb(a); } //Maak de boom maakBFSTree(); //Bepaal de snijkosten comp = dsu(n); snij = vi(n); welkset = vi(n,-1); snijset = vector<set<pair<ll,ii>>>(n); snijKosten(n - 1); //Bepaal het antwoord vi antw = vi(n, LLONG_MAX); antw[n - 1] = 0; set<ii> grens; grens.emplace(make_pair(0,n-1)); ll nu; while(grens.size() > 0){ nu = (*grens.begin()).y; grens.erase(*grens.begin()); for(ll buur : buren[nu]){ ll a = antw[nu] + 1; if(snij[buur] > a) a = snij[buur]; if(a < antw[buur]){ grens.erase(make_pair(antw[buur],buur)); antw[buur] = a; grens.emplace(make_pair(antw[buur],buur)); } } } nu = antw[0]; if(nu == LLONG_MAX) cout << -1 << endl; else cout << nu << endl; return 0; }