// Slower C++ solution:
#include <iostream>

#include <algorithm>

#include <queue>

#include <cstdio>

#include <cstring>

using namespace std;

const int MAXN = 200005;

struct Edge{

	int to,next,w;

}e[MAXN<<3];

struct E{

	int u,v,c;

	bool operator < (const E &b)const

	{

		return c<b.c;

	}

}t[MAXN<<1];

int head[MAXN<<3],n,m,fa[MAXN],id[MAXN],sz;

bool vis[MAXN<<3];

int getan(int x)

{

	return x==fa[x]?x:fa[x]=getan(fa[x]);

}

int cnt=0;

inline void insert(int u,int v,int w)

{

	e[++cnt].to=v,e[cnt].next=head[u],head[u]=cnt,e[cnt].w=w;

}

inline void work(int l,int r)

{

	for(int i=l;i<=r;++i){

		vis[t[i].u]=vis[t[i].v]=id[t[i].u]=id[t[i].v]=0;

		fa[t[i].u]=t[i].u;

		fa[t[i].v]=t[i].v;

	}

	for(int i=l,x,y;i<=r;++i)

		x=getan(t[i].u),y=getan(t[i].v),fa[x]=y;

	for(int i=l,x,y;i<=r;++i){

		x=getan(t[i].u),y=getan(t[i].v);

		if(!vis[t[i].u]){

			if(!id[x])id[x]=++sz;

			insert(t[i].u,id[x],0);

			insert(id[x],t[i].u,1);

			vis[t[i].u]=1;

		}

		if(!vis[t[i].v]){

			if(!id[y])id[y]=++sz;

			insert(t[i].v,id[y],0);

			insert(id[y],t[i].v,1);

			vis[t[i].v]=1;

		}

	}

}

struct Node{

	int x,v;

	bool operator < (const Node &b)const

	{

		return v>b.v;

	}

};

priority_queue<Node>q;

int d[MAXN<<3];

inline void dij()

{

	memset(vis,0,sizeof(vis));

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

	d[1]=0;

	q.push((Node){1,0});

	while(!q.empty()){

		Node x=q.top();

		q.pop();

		int u=x.x;

		if(vis[u])continue;

		vis[u]=true;

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

			int v=e[i].to;

			if(d[v]>d[u]+e[i].w){

				d[v]=d[u]+e[i].w;

				q.push((Node){v,d[v]});

			}

		}

	}

	cout<<(d[n]==0x3f3f3f3f?-1:d[n])<<endl;

}

int main()

{

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

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

		scanf("%d%d%d",&t[i].u,&t[i].v,&t[i].c);

	}

	sz=n;

	sort(t+1,t+m+1);

	int p=1;

	while(p<=m){

		int r=p;

		while(t[r+1].c==t[r].c)++r;

		work(p,r);

		p=r+1;

	}

	dij();

	return 0;

}


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

#include <algorithm>

#include <queue>

#include <cstdio>

#include <cstring>

using namespace std;

const int MAXN = 100005;

struct Edge{

	int to,next,w;

}e[MAXN<<3];

struct E{

	int u,v,c;

	bool operator < (const E &b)const

	{

		return c<b.c;

	}

}t[MAXN<<1];

int head[MAXN<<3],n,m,fa[MAXN],id[MAXN],sz;

bool vis[MAXN<<3];

int getan(int x)

{

	return x==fa[x]?x:fa[x]=getan(fa[x]);

}

int cnt=0;

inline void insert(int u,int v,int w)

{

	e[++cnt].to=v,e[cnt].next=head[u],head[u]=cnt,e[cnt].w=w;

}

inline void work(int l,int r)

{

	for(int i=l;i<=r;++i){

		vis[t[i].u]=vis[t[i].v]=id[t[i].u]=id[t[i].v]=0;

		fa[t[i].u]=t[i].u;

		fa[t[i].v]=t[i].v;

	}

	for(int i=l,x,y;i<=r;++i)

		x=getan(t[i].u),y=getan(t[i].v),fa[x]=y;

	for(int i=l,x,y;i<=r;++i){

		x=getan(t[i].u),y=getan(t[i].v);

		if(!vis[t[i].u]){

			if(!id[x])id[x]=++sz;

			insert(t[i].u,id[x],0);

			insert(id[x],t[i].u,1);

			vis[t[i].u]=1;

		}

		if(!vis[t[i].v]){

			if(!id[y])id[y]=++sz;

			insert(t[i].v,id[y],0);

			insert(id[y],t[i].v,1);

			vis[t[i].v]=1;

		}

	}

}

struct Node{

	int x,v;

	bool operator < (const Node &b)const

	{

		return v>b.v;

	}

};

priority_queue<Node>q;

int d[MAXN<<3];

inline void dij()

{

	memset(vis,0,sizeof(vis));

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

	d[1]=0;

	q.push((Node){1,0});

	while(!q.empty()){

		Node x=q.top();

		q.pop();

		int u=x.x;

		if(vis[u])continue;

		vis[u]=true;

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

			int v=e[i].to;

			if(d[v]>d[u]+e[i].w){

				d[v]=d[u]+e[i].w;

				q.push((Node){v,d[v]});

			}

		}

	}

	cout<<(d[n]==0x3f3f3f3f?-1:d[n])<<endl;

}

int main()

{

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

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

		scanf("%d%d%d",&t[i].u,&t[i].v,&t[i].c);

	}

	sz=n;

	sort(t+1,t+m+1);

	int p=1;

	while(p<=m){

		int r=p;

		while(t[r+1].c==t[r].c)++r;

		work(p,r);

		p=r+1;

	}

	dij();

	return 0;

}