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

#include<cstdio>

#include<vector>

#include<cstring>

#include<algorithm>

using namespace std;

const int MAXM = 200000;

const int MAXN = 300000;

struct edge{

	int u, v, c;

}edges[MAXM + 5];

bool operator < (edge a, edge b) {

	return a.c < b.c;

}

vector<int>G[MAXN + 5];

void addedge(int u, int v) {

	G[u].push_back(v);

	G[v].push_back(u);

}

int vcnt, fa[MAXN + 5], con[MAXN + 5], vis[MAXN + 5];

int Find(int x) {

	if( fa[x] == x ) return x;

	return fa[x] = Find(fa[x]);

}

void Union(int x, int y) {

	int fx = Find(x), fy = Find(y);

	if( fx != fy ) fa[fx] = fy;

}

int dis[MAXN + 5];

void bfs(int s) {

	memset(dis, -1, sizeof dis);

	queue<int>que; que.push(s);

	dis[s] = 0;

	while( !que.empty() ) {

		int f = que.front(); que.pop();

		for(int i=0;i<G[f].size();i++) {

			if( dis[G[f][i]] == -1 ) {

				dis[G[f][i]] = dis[f] + 1;

				que.push(G[f][i]);

			}

		}

	}

}

int main() {

	int N, M;

	scanf("%d%d", &N, &M);

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

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

	sort(edges+1, edges+M+1);

	vcnt = N; int lst = 1;

	for(int i=2;i<=M+1;i++) {

		if( edges[i].c != edges[i-1].c ) {

			for(int j=lst;j<i;j++) {

				fa[edges[j].u] = edges[j].u;

				fa[edges[j].v] = edges[j].v;

				con[edges[j].u] = con[edges[j].v] = 0;

				vis[edges[j].u] = vis[edges[j].v] = false; 

			}

			for(int j=lst;j<i;j++)

				Union(edges[j].u, edges[j].v);

			for(int j=lst;j<i;j++) {

				if( fa[edges[j].u] == edges[j].u )

					if( con[edges[j].u] == 0 )

						con[edges[j].u] = (++vcnt);

				if( fa[edges[j].v] == edges[j].v )

					if( con[edges[j].v] == 0 )

						con[edges[j].v] = (++vcnt);	

			}

			for(int j=lst;j<i;j++) {

				if( !vis[edges[j].u] ) {

					addedge(edges[j].u, con[Find(edges[j].u)]);

					vis[edges[j].u] = true;

				}

				if( !vis[edges[j].v] ) {

					addedge(edges[j].v, con[Find(edges[j].v)]);

					vis[edges[j].v] = true;

				}

			}

			lst = i;

		}

	}

	bfs(1);

	if( dis[N] == -1 ) puts("-1");

	else printf("%d\n", dis[N] / 2);

}

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

#include<algorithm>

#include<queue>

#include<vector>

using namespace std;

#define MAXN 100010

#define MAXM 200010

#define MAXK 2000100

#define INF 1000000000

struct edge

{

	int u,v,c;

}e[MAXM];

bool cmp(edge a,edge b)

{

	return a.c<b.c;

}

int fa[MAXN],n,N,m,u,v,c,im[MAXN];

vector<int>A;

int Find(int x)

{

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

}

void Union(int x,int y)

{

	x=Find(x),y=Find(y);

	fa[x]=y;

}

int Adj[MAXK],V[MAXK],nxt[MAXK],p;

void AddEdge(int u,int v)

{

	p++;V[p]=v;nxt[p]=Adj[u];

	Adj[u]=p;

}

int dis[MAXK];

bool vis[MAXK];

void SPFA()

{

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

		dis[i]=INF;

	queue<int>Q;

	Q.push(1);

	dis[1]=0;

	vis[1]=1;

	while(!Q.empty())

	{

		int u=Q.front();Q.pop();

		vis[u]=0;

		for(int i=Adj[u];i;i=nxt[i])

			if(dis[V[i]]>dis[u]+1)

			{

				dis[V[i]]=dis[u]+1;

				if(!vis[V[i]])

				{

					vis[V[i]]=1;

					Q.push(V[i]);

				}

			}

	}

}

int main()

{

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

	N=n;

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

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

	sort(e,e+m,cmp);

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

		fa[i]=i;

	int ls=0,lc=e[0].c;

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

		if(e[i].c!=lc)

		{

			for(int j=ls;j<i;j++)

				Union(e[j].u,e[j].v);

			for(int j=ls;j<i;j++)

			{

				int y=Find(e[j].v);

				if(!im[y])

					im[y]=++N,A.push_back(y);

				AddEdge(e[j].u,im[y]);

				AddEdge(im[y],e[j].u);

				AddEdge(e[j].v,im[y]);

				AddEdge(im[y],e[j].v);

			}

			for(int j=ls;j<i;j++)

				fa[e[j].v]=e[j].v,fa[e[j].u]=e[j].u;

			for(int j=0;j<A.size();j++)

				im[A[j]]=0;

			A.clear();

			ls=i,lc=e[i].c;

		}

	SPFA();

	if(dis[n]==INF) printf("-1\n");

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

}

// Fastest known solution for this problem: