// Original C++ solution (slower):
#include <cstdio>

#include <cstring>

#include <algorithm>

#include <cstdlib>

#include <vector>

#include <queue>

using namespace std;

#define N 300050

#define M 2400050

int head[N],to[M],nxt[M],n,m,cnt,val[M],tot,vis[N],dis[N],S,T;

priority_queue<pair<int,int> >q;

struct A {

	int x,y,z,id;

	bool operator < (const A &u) const {return z<u.z;}

}e[N];

vector<A>G[N];

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

	to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w;

}

int main() {

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

	int i,j;

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

		scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z); e[i].id=i;

		G[e[i].x].push_back(e[i]);

		G[e[i].y].push_back(e[i]);

	}

	tot=m; S=n+m+1,T=n+m+2;

	for(i=1;i<=n;i++) {

		sort(G[i].begin(),G[i].end());

		int lim=G[i].size();

		tot++;

		for(j=0;j<lim;j++) {

			add(G[i][j].id,tot,0);

			add(tot,G[i][j].id,1);

		}

		int k=0,l;

		for(j=0;j<lim;j=k) {

			for(;k<lim&&G[i][j].z==G[i][k].z;k++) ;

			for(l=j+1;l<k;l++) {

				add(G[i][l].id,G[i][l-1].id,0);

				add(G[i][l-1].id,G[i][l].id,0);

			}

		}

		for(j=0;j<lim;j++) {

			if(i==1) add(S,G[i][j].id,0);

			if(i==n) add(G[i][j].id,T,0);

		}

	}

	tot+=2;

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

	dis[S]=0;

	q.push(make_pair(0,S));

	while(!q.empty()) {

		int x=q.top().second; q.pop();

		if(vis[x]) continue;

		vis[x]=1;

		for(i=head[x];i;i=nxt[i]) if(dis[to[i]]>dis[x]+val[i]) {

			dis[to[i]]=dis[x]+val[i];

			q.push(make_pair(-dis[to[i]],to[i]));

		}

	}

	if(dis[T]>max(n,m)) puts("-1");

	else printf("%d\n",dis[T]+1);

}
























// Optimized solution to the same problem (faster):
#include <cstdio>

#include <cstring>

#include <algorithm>

#include <cstdlib>

#include <vector>

#include <queue>

using namespace std;

#define N 300050

#define M 2400050

int head[N],to[M],nxt[M],n,m,cnt,val[M],tot,vis[N],dis[N],S,T;

int Q[N],l,r;

priority_queue<pair<int,int> >q;

struct A {

	int x,y,z,id;

	bool operator < (const A &u) const {return z<u.z;}

}e[N];

vector<A>G[N];

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

	to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w;

}

char buf[100000],*p1,*p2;

#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)

int rd() {

	int x=0; char s=nc();

	while(s<'0') s=nc();

	while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc();

	return x;

}

void dfs(int x,int d) {

	dis[x]=d;vis[x]=1; Q[r++]=x;

	int i;

	for(i=head[x];i;i=nxt[i]) if(val[i]==0) {

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

			dfs(to[i],d);

		}

	}

}

int main() {

	n=rd(),m=rd();

	int i,j;

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

		e[i].x=rd(),e[i].y=rd(),e[i].z=rd(); e[i].id=i;

		G[e[i].x].push_back(e[i]);

		G[e[i].y].push_back(e[i]);

	}

	tot=m; S=n+m+1,T=n+m+2;

	for(i=1;i<=n;i++) {

		sort(G[i].begin(),G[i].end());

		int lim=G[i].size();

		tot++;

		for(j=0;j<lim;j++) {

			add(G[i][j].id,tot,0);

			add(tot,G[i][j].id,1);

		}

		int k=0,l;

		for(j=0;j<lim;j=k) {

			for(;k<lim&&G[i][j].z==G[i][k].z;k++) ;

			for(l=j+1;l<k;l++) {

				add(G[i][l].id,G[i][l-1].id,0);

				add(G[i][l-1].id,G[i][l].id,0);

			}

		}

		for(j=0;j<lim;j++) {

			if(i==1) add(S,G[i][j].id,0);

			if(i==n) add(G[i][j].id,T,0);

		}

	}

	Q[r++]=S; vis[S]=1; dis[S]=1;

	while(l<r) {

		int x=Q[l++];

		for(i=head[x];i;i=nxt[i]) {

			if(val[i]==0&&!vis[to[i]]) {

				dfs(to[i],dis[x]);

			}

		}

		for(i=head[x];i;i=nxt[i]) if(val[i]==1) {

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

				dis[to[i]]=dis[x]+val[i]; Q[r++]=to[i]; vis[to[i]]=1;

			}

		}

	}

	if(!dis[T]) puts("-1");

	else printf("%d\n",dis[T]);

}
























// Fastest known solution for this problem: