// 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: 1.7756177705223484x):
/*    三玖天下第一！！！  */

#include<bits/stdc++.h>

using namespace std;

const int maxn=1e5,maxm=2e5;

int n,m,lin[maxn+5]={},len=0,dis[maxn+5];bool vis[maxn+5]={};set<int> rail[maxn+5];

struct edge{int y,next,rk;}e[maxm*2+5];

inline void insert(int xx,int yy,int rr){e[++len].next=lin[xx];lin[xx]=len;e[len].y=yy;e[len].rk=rr;} 

inline int dread()

{

	int x=0;bool f=1;char ch=getchar();

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

	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}

	return f?x:-x;

}

inline void in(){n=dread();m=dread();for(int i=1,a,b,c;i<=m;i++) a=dread(),b=dread(),c=dread(),insert(a,b,c),insert(b,a,c);}

inline void dijkstra()

{

	memset(dis,0x3f,sizeof(dis));priority_queue< pair<int,pair<int,int> > > q;q.push(make_pair(-(dis[1]=0),make_pair(1,0)));

	while(!q.empty())

	{

		pair<int,int> seat=q.top().second;q.pop();if(vis[seat.first]) continue;vis[seat.first]=1;

		for(int i=lin[seat.first],extra=!(rail[seat.first].count(e[i].rk));i;i=e[i].next,extra=!(rail[seat.first].count(e[i].rk)))

		{

			if(dis[e[i].y]>dis[seat.first]+extra) q.push(make_pair(-(dis[e[i].y]=dis[seat.first]+extra),make_pair(e[i].y,e[i].rk))),rail[e[i].y].clear(),rail[e[i].y].insert(e[i].rk);

			else if(dis[e[i].y]==dis[seat.first]+extra) rail[e[i].y].insert(e[i].rk);

		}

	}printf("%d\n",dis[n]==0x3f3f3f3f?-1:dis[n]);

}

int main(){in();dijkstra();return 0;}