//vl coords;
//bool done = false;
//ll f(int u, int c){
//    ll tmp = (ll(u)<<20)+c;
//    if(!done)
//        coords.pb(tmp);
//    return tmp;
//}
//int name_of(ll x){
//    return lower_bound(all(coords),x)-coords.begin();
//}
//void __(){
//    _(int,n);
//    _(int,m);
//    _(vvi,a,m,vi(3));
//    vvi colors_nearby(n+1);
//    rep(i,m){
//        colors_nearby[a[i][0]].pb(a[i][2]);
//        colors_nearby[a[i][1]].pb(a[i][2]);
//        f(a[i][0],a[i][2]);
//        f(a[i][1],a[i][2]);
//    }
//    rep(i,1,n){
//        f(i,0);
//        for(int x : colors_nearby[i]){
//            f(i,x);
//        }
//    }
//    unique(coords);
//    done = true;
//    int s = name_of(f(1,0)), t = name_of(f(n,0));
//    n = sz(coords);
//    vvi adj(n),cost(n);
//    rep(i,m){
//        int u = name_of(f(a[i][0],a[i][2]));
//        int v = name_of(f(a[i][1],a[i][2]));
//        adj[u].pb(v);
//        adj[v].pb(u);
//        cost[u].pb(0);
//        cost[v].pb(0);
//    }
//    rep(i,1,sz(colors_nearby)-1){
//        for(ll x : colors_nearby[i]){
//            int u = name_of(f(i,0));
//            int v = name_of(f(i,x));
//            adj[u].pb(v);
//            adj[v].pb(u);
//            cost[u].pb(1);
//            cost[v].pb(1);
//        }
//    }
//    vi dist(n,MOD);
//    deque<int> bfs{s};
//    dist[s] = 0;
//    while(!bfs.empty()){
//        int u = bfs.front();
//        bfs.pop_front();
//        rep(i,sz(adj[u])){
//            int v = adj[u][i];
//            int c = cost[u][i];
//            if(dist[v] > dist[u]+c){
//                dist[v] = dist[u]+c;
//                if(c == 0)
//                    bfs.push_front(v);
//                else
//                    bfs.pb(v);
//            }
//        }
//    }
//    print dist[t] == MOD ? -1 : dist[t]/2;
//}
//
#include <iomanip>
#include <algorithm>
#include <queue>
#include <vector>
#include <utility>
#include <iostream>
#include <string>
#define pb push_back
#define REP_INT(i,l,r) for(int i = l; i <= r; ++i)
#define REP_ZERO_INT(i,r) for(int i = 0; i < r; ++i)
#define GET_REP_MACRO(_1,_2,_3,_4,NAME,...) NAME
#define rep(...) GET_REP_MACRO(__VA_ARGS__,REP_ANY,REP_INT,REP_ZERO_INT)(__VA_ARGS__)
#define all(v) (v).begin(), (v).end()
#define sz(v) ll(v.size())
#define T1 template<typename T> static
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<int> vi;
typedef vector<vi> vvi;
const ll MOD = 1e9 + 7;
T1 ostream& operator<<(ostream& stream, const vector<T>& t);
T1 vector<T> unique(vector<T>& arr){
    sort(all(arr));
    arr.erase(unique(all(arr)), arr.end());
    return arr;
}
T1 istream& read(T, T, istream& = cin);
T1 istream& operator>>(istream& stream, vector<T>& t){
    return read(all(t), stream);
}
T1 istream& read(T b, T e, istream& stream){
    for(T it = b; it != e; ++it)
        stream >> *it;
    return stream;
}
struct _print {
    string sep,end;
    bool space;
    ostream &stream;
    _print(string _sep=" ",string _end="\n",
            ostream &_stream = cout)
        : sep(_sep),end(_end),space(false),
            stream(_stream) {}
    ~_print() { stream << end; }
    template <typename T>
        _print &operator , (const T &t) {
            if (space) stream << sep;
            space = true;
            stream << t;
            return *this;
        }
};
#define print _print(),
#define INPUT_WITHOUT_INIT(type,name) type name; cin >> name
#define _IWI(type,name,...) type name(__VA_ARGS__); cin >> name
#define GET_INPUT_MACRO(_1,_2,_3,_4,_5,_6,_7,_8,NAME,...) NAME
#define _(...) GET_INPUT_MACRO(__VA_ARGS__,_IWI,_IWI,_IWI,_IWI,_IWI,_IWI,INPUT_WITHOUT_INIT)(__VA_ARGS__)
vl coords;
bool done = false;
ll f(int u, int c){
    ll tmp = (ll(u)<<20)+c;
    if(!done)
        coords.pb(tmp);
    return tmp;
}
int name_of(ll x){
    return lower_bound(all(coords),x)-coords.begin();
}
void __(){
    _(int,n);
    _(int,m);
    _(vvi,a,m,vi(3));
    vvi colors_nearby(n+1);
    rep(i,m){
        colors_nearby[a[i][0]].pb(a[i][2]);
        colors_nearby[a[i][1]].pb(a[i][2]);
        f(a[i][0],a[i][2]);
        f(a[i][1],a[i][2]);
    }
    rep(i,1,n){
        f(i,0);
        for(int x : colors_nearby[i]){
            f(i,x);
        }
    }
    unique(coords);
    done = true;
    int s = name_of(f(1,0)), t = name_of(f(n,0));
    n = sz(coords);
    vvi adj(n),cost(n);
    rep(i,m){
        int u = name_of(f(a[i][0],a[i][2]));
        int v = name_of(f(a[i][1],a[i][2]));
        adj[u].pb(v);
        adj[v].pb(u);
        cost[u].pb(0);
        cost[v].pb(0);
    }
    rep(i,1,sz(colors_nearby)-1){
        for(ll x : colors_nearby[i]){
            int u = name_of(f(i,0));
            int v = name_of(f(i,x));
            adj[u].pb(v);
            adj[v].pb(u);
            cost[u].pb(1);
            cost[v].pb(1);
        }
    }
    vi dist(n,MOD);
    deque<int> bfs{s};
    dist[s] = 0;
    while(!bfs.empty()){
        int u = bfs.front();
        bfs.pop_front();
        rep(i,sz(adj[u])){
            int v = adj[u][i];
            int c = cost[u][i];
            if(dist[v] > dist[u]+c){
                dist[v] = dist[u]+c;
                if(c == 0)
                    bfs.push_front(v);
                else
                    bfs.pb(v);
            }
        }
    }
    print dist[t] == MOD ? -1 : dist[t]/2;
}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);
        __();
}


Measured memory_bytes: 82664