#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;
#define all(x) begin(x),end(x)
#define rep(i,a,b) for(int i=(a);i<(b);++i)
#define sz(x) int(x.size())
const int oo = 1e9;
struct Tree {
    typedef int T;
    static constexpr T unit = oo;
    T f(T a, T b) {return min(a,b);}
    vector<T> s; int n;
    Tree (int n=0, T def = unit):s(2*n,def),n(n) {}
    void update(int pos,T val) {
        for(s[pos+=n]=val;pos/=2;)
            s[pos]=f(s[pos*2],s[pos*2+1]);
    }
    T query(int b, int e) {
        T ra = unit, rb=unit;
        for(b+=n,e+=n;b<e;b/=2,e/=2) {
            if(b%2) ra=f(ra,s[b++]);
            if(e%2) rb=f(s[--e],rb);
        }
        return f(ra,rb);
    }
};
int main() {
    cin.tie(NULL);
    cin.sync_with_stdio(false);

    int n,m; cin >> n >> m;
    vvi adj(n);
    for(int i=0;i<m;++i) {
        int u,v; cin >> u >> v;
        --u,--v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    auto bfs = [&](int s) {
        vi d(n,oo);
        d[s]=0;
        vi q = {s};
        for(int i=0;i<q.size();++i) {
            int at= q[i];
            for(int to : adj[at]) {
                if(d[to]==oo) {
                    d[to]=d[at]+1;
                    q.push_back(to);
                }
            }
        }
        return d;
    };
    // auto ds = bfs(0);
    auto dt = bfs(n-1);
    vi par(n,-1);
    vvi tree(n);
    for(int i=0;i<n-1;++i) {
        for(int j : adj[i]) {
            if(dt[j]==dt[i]-1) {
                par[i]=j;
            }
        }
    }
    vi skipedge(n,oo);
    for(int i=0;i<n-1;++i) {
        tree[par[i]].push_back(i);
    }
    vi in(n),out(n),s(n,1);
    int C=0;
    auto dfsin = [&](auto&& self, int at) -> void {
        in[at]=C++;
        for(int to : tree[at]) {
            self(self,to);
            s[at]+=s[to];
        }
        out[at]=C;
    };
    dfsin(dfsin,n-1);
    vector<multiset<int>> upds(n, {oo});
    Tree seg(n);
    auto myadd = [&](int at, int sgn) -> void  {
        for(int to : adj[at]) {
            if(to==par[at]) continue;
            if(in[at]<=in[to] and in[to]<out[at]) {
                // child
                continue;
            }
            if(sgn==-1) {
                auto it = upds[in[to]].find(dt[at]+1+dt[to]);
                upds[in[to]].erase(it);
            } else {
                upds[in[to]].insert(dt[at]+1+dt[to]);
            }
            seg.update(in[to],*upds[in[to]].begin());

        }
    };
    auto del = [&](auto&& self, int at, int sgn) -> void {
        myadd(at,sgn);
        for(int to : tree[at]) {
            self(self,to,sgn);
        }
    };
    for(auto& v : tree) {
        sort(all(v),[&](int i, int j) {return s[i]>s[j];});
    }
    auto dfs = [&](auto&& self, int at,bool keep=0) -> void {
        bool heavy = 1;
        int h=-1;
        for(int to : tree[at]) {
            if(!heavy) {
                self(self,to,0);
            } else h = to;
            heavy=0;
        }
        if(h!=-1) self(self,h,1);
        heavy=1;
        for(int to : tree[at]) {
            if(!heavy) {
                del(del,to,1);
            }
            heavy=0;
        }
        // mezelf adden
        myadd(at,1);

        // subtree goed
        skipedge[at] = min(seg.query(0,in[at]),seg.query(out[at],n))-dt[at];


        // voeg mezelf toe
        if(!keep) {
            del(del,at,-1);
        }
    };
    dfs(dfs,n-1,1);

    struct el {
        int d;
        int at;
        bool operator<(const el& o) const {
            return d>o.d;
        }
    };
    priority_queue<el> pq;
    vi dp(n,oo);
    auto push = [&](int d, int at) {
        if(d<dp[at]) {
         dp[at]=d;
            pq.push({d,at});
        }
    };
    push(0,n-1);
    while(!pq.empty()) {
        auto e = pq.top(); pq.pop();
        if(e.d!=dp[e.at]) continue;
        for(int to : adj[e.at]) {
            push(max(e.d+1,skipedge[to]),to);
        }
    }
    if(dp[0]==oo) dp[0]=-1;
    cout << dp[0] << '\n';
}
/*
5 7
1 2
2 3
2 4
3 4
3 5
4 5
1 5

*/