#include <iostream> #include <vector> #include <string> #include <algorithm> #include <queue> #include <set> using namespace std; typedef long long ll; const int MAXN = 200005; const ll INF = 1e9; struct Node { vector<int> nei; ll ds; ll dt; ll speciald = INF; ll cost = 0; ll blockedby = -1; bool vis = false; }; Node graph[MAXN]; int n, m; int s, t; void bfsDS() { queue<int> q; q.push(s); graph[s].vis = true; graph[s].ds = 0; while (!q.empty()) { int u = q.front(); q.pop(); for (int v : graph[u].nei) { if (graph[v].vis) continue; graph[v].vis = true; graph[v].ds = graph[u].ds + 1; q.push(v); } } } void bfsDT() { queue<int> q; q.push(t); graph[t].vis = true; graph[t].dt = 0; while (!q.empty()) { int u = q.front(); q.pop(); for (int v : graph[u].nei) { if (graph[v].vis) continue; graph[v].vis = true; graph[v].dt = graph[u].dt + 1; q.push(v); } } } void clearvis() { for (int i = 0; i < n; i++) { graph[i].vis = false; } } void bfsCOST(ll maxcost) { if (graph[s].cost > maxcost) return; queue<int> q; q.push(s); graph[s].vis = true; while (!q.empty()) { int u = q.front(); q.pop(); for (int v : graph[u].nei) { if (graph[v].vis) continue; if (graph[v].cost > maxcost) continue; graph[v].vis = true; q.push(v); } } } int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m; for (int i = 0; i < m; i++) { int u, v; cin >> u >> v; u--; v--; graph[u].nei.push_back(v); graph[v].nei.push_back(u); } s = 0; t = n-1; clearvis(); bfsDS(); clearvis(); bfsDT(); clearvis(); vector<int> vxs(n); for (int i = 0; i < n; i++) vxs[i] = i; sort(vxs.begin(), vxs.end(), [&](const int& a, const int& b) { return graph[a].dt < graph[b].dt; }); vector<vector<int>> lvls(n); for (int i = 0; i < n; i++) { lvls[graph[i].dt].push_back(i); } for (vector<int>& l : lvls) { for (int u : l) { if (u == t) { graph[u].speciald = 0; continue; } set<int> currblockedby; int numlower = 0; for (int v: graph[u].nei) { if (graph[v].dt < graph[u].dt) { if (graph[v].blockedby != -1) { currblockedby.insert(graph[v].blockedby); } else { numlower++; } } } if (currblockedby.size() + numlower >= 2) { for (int i: currblockedby) { graph[i].speciald = min(graph[i].speciald, 2 * graph[u].dt - graph[i].dt); graph[i].blockedby = -1; } graph[u].speciald = graph[u].dt; } else if (currblockedby.size() == 1) { graph[u].blockedby = *currblockedby.begin(); } else { graph[u].blockedby = u; } } for (int u : l) { if (u == t || graph[u].blockedby == -1) { continue; } for (int v: graph[u].nei) { if (graph[v].dt == graph[u].dt) { if (graph[v].blockedby != -1 || graph[v].blockedby != graph[u].blockedby) { int i = graph[u].blockedby; graph[i].speciald = min(graph[i].speciald, 2 * graph[u].dt - graph[i].dt + 1); graph[i].blockedby = -1; graph[u].blockedby = -1; break; } } } } } for (int i = 0; i < n; i++) { graph[i].cost = min(graph[i].ds + graph[i].speciald, INF); if (graph[i].blockedby != -1 && graph[graph[i].blockedby].blockedby == -1) { graph[i].cost = 0; } else if (graph[i].blockedby != -1){ graph[i].cost = INF; } } ll lo = 0; ll hi = INF-10; while (lo < hi) { ll mid = (lo + hi) / 2; clearvis(); bfsCOST(mid); if (graph[t].vis) { hi = mid; } else { lo = mid + 1; } } if (lo > INF/2) { cout << -1 << endl; } else { cout << lo << endl; } return 0; }