// 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.2349988482680816x):
///

/**

 * @Samaritan

 */

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;



#define pb emplace_back

#define fi first

#define se second

#define PII pair<int, int>

#define PLL pair<LL, LL>

#define PLI pair<LL, int>



LL quick_pow (LL a, LL b, LL mod) {

    LL ans = 1, base = a;

    while (b) {

        if (b & 1) (ans *= base) %= mod;

        b >>= 1;

        (base *= base) %= mod;

    }

    return ans;

}



inline int log2(const float &x) {

    return ((unsigned &) x >> 23 & 255) - 127;

}



void show(int arr[], int len) {

    for (int i = 0; i <= len; ++i) {

        cout << arr[i] << " ";

    }

    cout << endl;

}

struct node {

    int dist, id;

    node() {

    }

    node(int d, int i) : dist(d), id(i) {}

    bool operator < (const node& k) const {

        if (dist == k.dist)

            return id <= k.id;

        return dist < k.dist;

    }

};



const int mod = 998244353;

const int N = 1e5 + 5;

const int logN = 20;

const int INF = 0x3f3f3f3f;



vector<PII> edge[N];

int dist[N];

set<int> type[N];

//bool vis[N];



void work(int n) {

    memset(dist, INF, sizeof dist);

    dist[1] = 0;

    priority_queue<PII> p;

    p.push({0, 1});

    while(!p.empty()) {

        int now = p.top().second;

        int val = -p.top().first;

        p.pop();

        if (dist[now] < val)

            continue;

        for (const auto& pp : edge[now]) {

            int to = pp.first;

            int now_type = pp.second;

            int now_val = val;

            if (!type[now].count(now_type))

                now_val++;

//            int to_ca=ca+(!type[now].count(to_com));

            if (dist[to] > now_val) {

                dist[to] = now_val;

                p.push({-now_val, to});

                type[to].clear();

                type[to].insert(now_type);

            } else if(dist[to] == now_val) {

                type[to].insert(now_type);

            }

        }

    }

    return;

    memset(dist, INF, sizeof(dist[0]) * (n + 3));

    priority_queue<PII, vector< PII >, greater<> > pq;

    dist[1] = 0;

    pq.push({0, 1});

    while (!pq.empty()) {

        int pos = pq.top().second;

        int now_dist = pq.top().first;

        pq.pop();

//        if (vis[pos]) continue;

//        vis[pos] = true;

        if (now_dist > dist[pos]) continue;

        for (const auto& p : edge[pos]) {

            int to = p.first;

            int now_type = p.second;

            int now_val = dist[pos];

            if (!type[pos].count(now_type))

                now_val++;

            if (now_val < dist[to]) {

                dist[to] = now_val;

                type[to].clear();

                type[to].insert(now_type);

                pq.push({dist[to], to});

            } else if (now_val == dist[to]) {

                type[to].insert(now_type);

            }

        }

    }

}



int main() {

    int n, m;

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

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

        edge[i].clear();

    int l, r, c;

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

        scanf("%d %d %d", &l, &r, &c);

        edge[l].pb(r, c);

        edge[r].pb(l, c);

    }

    work(n);



    if (dist[n] >= INF)

        puts("-1");

    else

        printf("%d\n", dist[n]);

    return 0;

}