#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <unordered_map>
#include <queue>
#include <deque>
#include <cmath>
#include <math.h>
#include <string>
#include <time.h>
#include <random>
#include <memory.h>
#include <bitset>
using namespace std;

#define FILE0
#define MAGIC0
mt19937 rnd(time(0)); //rnd()

#define ll long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define mii map<int, int>
#define mll map<ll, ll>
#define msl map<string, ll>
#define mls map<ll, string>
#define MOD (1000000007ll)
#define MOD2 (1000000009ll)
#define BIGMOD (1000000000000000007ll)
#define RMOD int(5e8 + rnd() % (int) 5e8)
#define fast ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

#ifdef FILE1
ifstream in("input.txt");
ofstream out("output.txt");
#endif
#ifdef MAGIC1
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
#endif

bool isPrime(ll a)
{
	ll i;
	for (i = 2; i*i <= a; i++)
	{
		if (a%i == 0)
		{
			return 0;
		}
	}
	return (a != 1);
}

bool isPalindrom(const string &s, int l, int r)
{
	for (int i = 0; i < (r - l + 1) / 2; i++)
	{
		if (s[l + i] != s[r - i])
		{
			return 0;
		}
	}
	return 1;
}

template <class type1> type1 gcd(type1 a, type1 b)
{
	type1 t;
	while (b)
	{
		t = b;
		b = a%b;
		a = t;
	}
	return a;
}

ll positiveMod(ll v, ll md)
{
	v = v%md;
	if (v < 0)
	{
		v += md;
	}
	return v;
}

//-----------------------------------------------------end--------------------------------------//

map <int, vector <int> > gr[200005];
map <int, int> len[200005];

int used[200005];

set <pair<pii, pii> > inf; // {{len, type}, {vertex, last edge color}}
map <int, int> inf2[200005];

int main()
{
	fast;

	int n, m, i, j, a, b, c, e;

	cin >> n >> m;

	if (n == 1)
	{
		cout << 0 << "\n";

		return 0;
	}

	for (i = 0; i < m; i++)
	{
		cin >> a >> b >> c;

		gr[a][c].push_back(b);
		gr[b][c].push_back(a);
	}

	used[1] = 1;
	for (auto& it : gr[1])
	{
		len[1][it.first] = 1;
		for (auto& itt : it.second)
		{
			len[itt][it.first] = 1;

			inf.insert({ {1, 0}, {itt, it.first} });

			if (used[itt] == 0)
			{
				used[itt] = 1;
				inf.insert({ {1, 1}, {itt, it.first} });
			}
		}
	}

	while (!inf.empty())
	{
		pair<pii, pii> e = *inf.begin();
		inf.erase(inf.begin());

		if (e.first.second == 0)
		{
			for (auto& itt : gr[e.second.first][e.second.second])
			{
				if (len[itt].count(e.second.second) == 0)
				{
					len[itt][e.second.second] = e.first.first;

					inf.insert({ {e.first.first, 0}, {itt, e.second.second} });

					if (used[itt] == 0)
					{
						used[itt] = 1;

						inf.insert({ { e.first.first, 1 },{ itt, e.second.second } });
					}
				}
			}
		}
		else
		{
			for (auto& it : gr[e.second.first])
			{
				for (auto& itt : it.second)
				{
					if (len[itt].count(it.first) == 0)
					{
						len[itt][it.first] = e.first.first + 1;

						inf.insert({ { e.first.first + 1, 0 },{ itt, it.first } });

						if (used[itt] == 0)
						{
							used[itt] = 1;
							inf.insert({ { e.first.first + 1, 1 },{ itt, it.first } });
						}
					}
				}
			}
		}
	}

	int res = MOD;
	for (auto it : len[n])
	{
		if (it.second < res)
		{
			res = it.second;
		}
	}

	if(res == MOD)
	{
		cout << -1 << "\n";
	}
	else
	{
		cout << res << "\n";
	}

	return 0;
}

Measured memory_bytes: 98304