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

#include <iostream>

#include <cstring>

#include <cstdio>

#include <queue>

#define N 200005

using namespace std;



int n, m, cnt, tot, id[N], head[N << 3], dis[N << 3]; 

struct node

{

	int u, v, w;

	bool operator < (const node &p) const

		{

			return w < p.w; 

		}

} a[N];

struct edge { int to, next, cost; } e[N << 3];

bool vis[N << 3]; 



template < typename T >

inline T read()

{

	T x = 0, w = 1; char c = getchar();

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

	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();

	return x * w; 

}



inline void adde(int u, int v, int w) { e[++cnt] = (edge) { v, head[u], w }; head[u] = cnt; }



void bfs()

{

	memset(dis, 0x3f, sizeof(dis)); dis[1] = 0;

	deque<int> q;

	q.push_front(1);

	while(!q.empty())

	{

		int u = q.front(); q.pop_front();

		if(vis[u]) continue; vis[u] = 1; 

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

		{

			int v = e[i].to;

			if(dis[v] > dis[u] + e[i].cost)

			{

				dis[v] = dis[u] + e[i].cost; 

				if(!e[i].cost) q.push_front(v);

				else q.push_back(v); 

			}

		}

	}

}



int main()

{

	tot = n = read <int> (), m = read <int> (); 

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

		a[i].u = read <int> (), a[i].v = read <int> (), a[i].w = read <int> ();

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

	int last = a[1].w;

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

		if(a[i].w != a[last].w)

		{

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

			{

				if(!id[a[j].u]) id[a[j].u] = ++tot;

				if(!id[a[j].v]) id[a[j].v] = ++tot;

				adde(a[j].u, id[a[j].u], 1), adde(id[a[j].u], a[j].u, 0);

				adde(a[j].v, id[a[j].v], 1), adde(id[a[j].v], a[j].v, 0);

				adde(id[a[j].u], id[a[j].v], 0), adde(id[a[j].v], id[a[j].u], 0);

			}

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

				id[a[j].u] = id[a[j].v] = 0; 

			last = i; 

		}

	bfs();

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

	return 0; 

}


// Faster C++ solution for the same problem (measured speedup: 1.132350401930035x):
/*    三玖天下第一！！！  */

#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;}