// Slower C++ solution:
#include <stdio.h>

#include <string.h>

#include <algorithm>

#define ME 200000

#define MN 1400000

#define INF 0x7f7f7f7f

int n,m,pl,ql,pc;

int lst[MN+5],pnt[MN+5];

int dis[MN+5]; bool usd[MN+5];

int hd[MN+5],to[MN+5],val[MN+5],nxt[MN+5],rn=0;

struct edge{int p,q,c;}e[ME+5];

bool cmp(edge a,edge b){return a.c<b.c;}

struct DEQUE{

	int mem[MN*2+5],hd,tl;

	DEQUE(){hd=MN,tl=MN+1;}

	int front(){return mem[hd];}

	bool empty(){return hd==tl-1;}

	void hdpush(int x){mem[++hd]=x;}

	void hdpop(){--hd;}

	void tlpush(int x){mem[--tl]=x;}

	void tlpop(){++tl;}

}q;

inline void add(int u,int v,int c){

	++rn;

	nxt[rn]=hd[u],hd[u]=rn;

	to[rn]=v,val[rn]=c;

}

int main(){

	memset(dis,0x7f,sizeof(dis));

	memset(hd,0xff,sizeof(hd));

	scanf("%d%d",&n,&m); pc=n;

	for(int i=1;i<=m;i++)

		scanf("%d%d%d",&e[i].p,&e[i].q,&e[i].c);

	std::sort(e+1,e+1+m,cmp);

	for(int i=1;i<=m;i++){

		if(lst[e[i].p]!=e[i].c){

			lst[e[i].p]=e[i].c,pnt[e[i].p]=(++pc);

			add(e[i].p,pnt[e[i].p],1),add(pnt[e[i].p],e[i].p,0);

		}

		if(lst[e[i].q]!=e[i].c){

			lst[e[i].q]=e[i].c,pnt[e[i].q]=(++pc);

			add(e[i].q,pnt[e[i].q],1),add(pnt[e[i].q],e[i].q,0);

		}

		add(pnt[e[i].p],pnt[e[i].q],0),add(pnt[e[i].q],pnt[e[i].p],0);

	}

	dis[1]=0; q.tlpush(1);

	for(int d=0;;d++){

		while(1){

			int u=q.front();

			if(usd[u]){q.hdpop();continue;}

			if(dis[u]!=d)break;

			q.hdpop(); usd[u]=true;

			for(int i=hd[u];i!=-1;i=nxt[i]){

				if(!usd[to[i]]){

					if(val[i]==0){

						if(dis[to[i]]>d){

							dis[to[i]]=d;

							q.hdpush(to[i]);

						}

					}else{

						if(dis[to[i]]>d+1){

							dis[to[i]]=d+1;

							q.tlpush(to[i]);

						}

					}

				}

			}

		}

		if(dis[n]!=INF||q.empty())break;

	}

	printf("%d",dis[n]==INF?-1:dis[n]);

}

// Faster C++ solution for the same problem (measured speedup: 12.071597286580152x):
#include<cstdio>

#include<iostream>

#include<cstring>

#include<queue>

#include<map>

#define RG register

using namespace std;

const int N=1e5+10, M=2e5+10;

const long long mod=1e5+7;

struct dabt{

	int next,to,dis;

}e[M*6],hsh[M*2];

struct node{

	int u,dis;

	bool operator < (const node&x)const{return x.dis<dis;}

};

int n,m,head[N+2*M],k,dist[N+2*M],st[2*M],ed[2*M],cnt,kk;

int kh,h[mod+1];

bool vis[N+2*M];

template<typename I> inline void read(I &ot){

	I ch=getchar(), x=0, f=1;

	while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();	}

	while(ch>='0' && ch<='9'){x=x*10+ch-'0'; ch=getchar();	}

	ot=x*f;}

template<typename I, typename... U> inline void read(I &x,U&... y){read(x); read(y...);}

inline void add(int from,int to,int d){

	e[++k]=(dabt){head[from],to,d}; head[from]=k;

	e[++k]=(dabt){head[to],from,d}; head[to]=k;

}

inline void adde(int from,int to,int d){hsh[++kh]=(dabt){h[from],to,d}; h[from]=kh;}

inline int id(int a,int b){

	int ss=((long long)a*n%mod+b)%mod;

	for(int i=h[ss];i;i=hsh[i].next)

	{

		int v=hsh[i].to;

		if(st[v]==a && ed[v]==b) return hsh[i].dis;

	}

	st[++kk]=a; ed[kk]=b;

	adde(ss,kk,++cnt);

	return cnt;

}

/*

map<pair<int,int>,int> P;

int id(int u,int c) {

    if(P.find(make_pair(u,c))!=P.end())

        return P[make_pair(u,c)];

    return P[make_pair(u,c)]=++cnt;

}*/

inline void dij()

{

	priority_queue<node> pn;

	while(!pn.empty()) pn.pop();

	for(int i=1;i<=n+m*2;i++) dist[i]=2e9;

	pn.push((node){1,0}); dist[1]=0;

	while(!pn.empty())

	{

		node u=pn.top(); pn.pop();

		int x=u.u; vis[x]=1;

		for(int i=head[x];i;i=e[i].next)

		{

			int v=e[i].to;

			if(dist[v]>dist[x]+e[i].dis)

			{

				dist[v]=dist[x]+e[i].dis;

				if(!vis[v]) pn.push((node){v,dist[v]});

			}

		}

	}

}

int main()

{

//	freopen("Snuke's Subway Trip.in","r",stdin);

//	freopen(". out","w",stdout);

	read(n,m); cnt=n;

	for(int i=1,a,b,c;i<=m;i++)

	{

		read(a,b,c);

		int id1=id(a,c), id2=id(b,c);

		add(a,id1,1); add(id1,id2,0); add(id2,b,1);

	}

	dij();

	printf("%d\n",dist[n]==2e9 ? -1 : dist[n]/2);

//	for(int i=1;i<=9;i++) printf("%d\n",dist[i]);

	//fclose(stdin); fclose(stdout);

	return 0;

}