#include <bits/stdc++.h>
using namespace std;
template<class T> ostream& operator<<(ostream &os, vector<T> V) { os << "[ "; 
	for(auto v:V)os << v << " "; return os << "]";
}
template<class T> ostream& operator<<(ostream &os, set<T> S){ os << "{ "; 
	for(auto s:S) os<<s<<" ";  return os<<"}"; 
}
template<class L, class R> ostream& operator<<(ostream &os, pair<L,R> P) {
	return os<<"("<<P.first<<","<< P.second << ")";
}
template<class L, class R> ostream& operator<<(ostream &os, map<L,R> M) {
	os<<"{ ";for(auto m:M)os<<"("<<m.F<<":"<<m.S<<")";
	return os<<"}";
}
#define cerr cout
#define TRACE
#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
	cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
	const char* comma = strchr(names + 1, ',');cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...) 1
#endif
#define ll long long
#define ld long double
#define vll vector<ll>
#define pll pair<ll,ll>
#define vpll vector<pll>
#define I insert 
#define pb push_back
#define F first
#define S second
#define endl "\n"
#define mp make_pair
#define all(v) (v).begin(),(v).end()
#define For(i,n) for(int i=0;i<(int)n;++i)
#define Rev(i,n) for(int i=(int)n-1;i>=0;--i)
#define Rep(i,n) for(int i=1;i<=(int)n;++i)
typedef vector<int> vi;
typedef pair<int,int> pii;
typedef pair<pii,int> ppi;
typedef vector<pii> vpii;
#define fio ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)

const int N = 1e6 + 100;
const int INF = 1e9;

int U[N] , V[N] , C[N];
int n , m;


vpii G[N];

int dis[N];


int main(){
	fio; cout<<fixed<<setprecision(25);	
	cin >> n >> m;

	map<pii , int> exist;
	int idx = n+1 , u , v , c;
	for(int i = 1;i <= m;++i){
		cin >> u >> v >> c;
		if(exist.find(mp(u , c)) == exist.end()){
			exist[mp(u , c)] = idx++;
		}
		if(exist.find(mp(v , c)) == exist.end()){
			exist[mp(v , c)] = idx++;
		}
		G[u].pb(mp(exist[mp(u , c)] , 1));
		G[exist[mp(u , c)]].pb(mp(u , 0));
		G[v].pb(mp(exist[mp(v , c)] , 1));
		G[exist[mp(v , c)]].pb(mp(v , 0));
		G[exist[mp(u , c)]].pb(mp(exist[mp(v , c)] , 0));
		G[exist[mp(v , c)]].pb(mp(exist[mp(u , c)] , 0));
	}
	for(int i =1 ;i < idx ; ++i){
		dis[i] = INF;
	}
	deque<pii> Q;
	// priority_queue<pair<pii, int> , vector<pair<pii,int> > , greater<pair<pii,int> > >Q;
	// Q.push(mp(mp(0 , -1) , 1));
	Q.pb(mp(0 , 1));
	dis[1] = 0;
	//it.F is distance
	//it.S is vertex
	while(Q.size() > 0){
		auto it = Q.front();
		// trace(it);
		if(it.S == n){
			cout << it.F << endl;
			return 0;
		}
		Q.pop_front();
		for(auto e : G[it.S]){
			int w = e.S + it.F;
			if(dis[e.F] > w){
				dis[e.F] = w;
				if(e.S == 1){
					Q.pb(mp(dis[e.F] , e.F));
				}
				else{
					Q.push_front(mp(dis[e.F] , e.F));
				}
			}
		}
	} 	
	cout << -1 << endl;








	return 0;
}

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 400005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
	if(c == '-') f = -1;
	c = getchar();
    }
    while(c >= '0' && c <= '9') {
	res = res * 10 +c - '0';
	c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
	out(x / 10);
    }
    putchar('0' + x % 10);
}
struct node {
    int to,next,val;
}E[MAXN * 10];
int head[MAXN],sumE;
int N,M,Ncnt;
int c[MAXN],dis[MAXN];
vector<int> to[MAXN];
bool vis[MAXN];
priority_queue<pii > Q;
void add(int u,int v,int c) {
    E[++sumE].to = v;
    E[sumE].next = head[u];
    E[sumE].val = c;
    head[u] = sumE;
}
void Solve() {
    read(N);read(M);
    int q,p;
    Ncnt = M;
    for(int i = 1 ; i <= M ; ++i) {
	read(q);read(p);read(c[i]);
	to[q].pb(i);to[p].pb(i);
    }
    for(int i = 1 ; i <= N ; ++i) {
	sort(to[i].begin(),to[i].end(),[](int a,int b) {return c[a] < c[b];});
	int nw = ++Ncnt;
	for(int j = 0 ; j < to[i].size() ; ++j) {
	    int p = j;
	    while(p < to[i].size() - 1 && c[to[i][p + 1]] == c[to[i][j]]) ++p;
	    for(int h = j + 1 ; h <= p ; ++h) {
		add(to[i][j],to[i][h],0);
		add(to[i][h],to[i][j],0);
	    }
	    add(to[i][j],nw,0);
	    add(nw,to[i][j],1);
	    j = p;
	}
    }
    for(int i = 1 ; i <= Ncnt ; ++i) dis[i] = 1e9;
    for(auto t : to[1]) {dis[t] = 1;Q.push(mp(-1,t));}
    while(!Q.empty()) {
	pii now = Q.top();Q.pop();
	if(vis[now.se]) continue;
	int u = now.se;vis[u] = 1;
	for(int i = head[u] ; i ; i = E[i].next) {
	    int v = E[i].to;
	    if(dis[v] > dis[u] + E[i].val) {
		dis[v] = dis[u] + E[i].val;
		Q.push(mp(-dis[v],v));
	    }
	}
    }
    int ans = 1e9;
    for(auto t : to[N]) ans = min(ans,dis[t]);
    if(ans >= 1e9) {
	puts("-1");return;
    }
    else {out(ans);enter;}
}

int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}
