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

using ll = long long;
using LL = long long;
using i64 = long long;

struct SegTree {
    vector<int> arr;
    int s;

    void update(int p, int v) {
        p += s;
        arr[p] = v;

        for (p >>= 1; p; p >>= 1)
            arr[p] = min(arr[2 * p], arr[2 * p + 1]);
    }

    int query(int l, int r) {
        int ans = 1e9;
        for (l += s, r += s; l < r; l >>= 1, r >>= 1) {
            if (l & 1) ans = min(ans, arr[l++]);
            if (r & 1) ans = min(ans, arr[--r]);
        }
        return ans;
    }

    SegTree(int n) {
        s = 1 << (int)ceil(log2(n));
        arr.resize(2 * s, 1e9);
    }
};

void solve() {
    int n, m; cin >> n >> m;
    vector<vector<int>> adj(n);
    for (int i = 0; i < m; i++) {
        int u, v; cin >> u >> v;
        adj[u - 1].push_back(v - 1);
        adj[v - 1].push_back(u - 1);
    }

    queue<tuple<int, int, int>> q;
    q.emplace(n - 1, -2, 0);
    vector<int> par(n, -1), dst(n, 1e9);
    while (!q.empty()) {
        auto [x, p, d] = q.front(); q.pop();
        if (par[x] != -1) continue;
        par[x] = p;
        dst[x] = d;

        for (auto u: adj[x])
            q.emplace(u, x, d + 1);
    }

    vector<vector<int>> treeadj(n);
    for (int i = 0; i < n - 1; i++)
        treeadj[par[i]].push_back(i);

    int timer = 0;
    vector<int> tin(n), tout(n);
    auto dfs1 = [&](auto &&dfs1, int node) -> void {
        tin[node] = timer++;
        for (auto u: treeadj[node])
            dfs1(dfs1, u);
        tout[node] = timer;
    };

    dfs1(dfs1, n - 1);

    SegTree segtree(n);
    vector<multiset<int>> edges(n);
    for (int i = 0; i < n; i++) edges[i].insert(1e9);

    auto score = [&](int lo, int hi) {
        return dst[hi] + dst[lo];
    };

    vector<int> adjusted(n);

    auto dfs = [&](auto &&dfs, int node) -> void {
        for (auto u: treeadj[node]) {
            dfs(dfs, u);
        }

        for (auto u: adj[node]) {
            if (tin[node] <= tin[u] && tin[u] < tout[node]) {
                if (par[u] != node) {
                    edges[u].erase(edges[u].find(score(u, node)));
                    segtree.update(tin[u], *edges[u].begin());
                }
            } else if (u != par[node]) {
                edges[node].insert(score(node, u));
                segtree.update(tin[node], *edges[node].begin());
            }
        }

        adjusted[node] = segtree.query(tin[node], tout[node]) - dst[node] + 1;
    };

    dfs(dfs, n - 1);
    adjusted[n - 1] = 0;

    auto check = [&](int limit) {
        queue<pair<int, int>> q;
        q.emplace(0, 0);
        vector<int> dst(n, 1e9);

        while (!q.empty()) {
            auto [x, d] = q.front(); q.pop();
            if (dst[x] != 1e9) continue;
            if (d + adjusted[x] > limit) continue;
            if (x == n - 1) return true;
            dst[x] = d;

            for (auto u: adj[x]) {
                q.emplace(u, d + 1);
            }
        }

        return false;
    };

    int l = 0, r = 3 * n;
    while (r - l > 1) {
        int m = (l + r) / 2;
        if (check(m)) r = m;
        else l = m;
    }

    if (r == 3 * n) r = -1;
    cout << r << '\n';
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(nullptr);
    solve();
}