Problem:
Score : 600 points

Problem Statement

Snuke's town has a subway system, consisting of N stations and M railway lines. The stations are numbered 1 through N. Each line is operated by a company. Each company has an identification number.

The i-th ( 1 \leq i \leq M ) line connects station p_i and q_i bidirectionally. There is no intermediate station. This line is operated by company c_i.

You can change trains at a station where multiple lines are available.

The fare system used in this subway system is a bit strange. When a passenger only uses lines that are operated by the same company, the fare is 1 yen (the currency of Japan). Whenever a passenger changes to a line that is operated by a different company from the current line, the passenger is charged an additional fare of 1 yen. In a case where a passenger who changed from some company A's line to another company's line changes to company A's line again, the additional fare is incurred again.

Snuke is now at station 1 and wants to travel to station N by subway. Find the minimum required fare.

Constraints

2 \leq N \leq 10^5

0 \leq M \leq 2×10^5

1 \leq p_i \leq N (1 \leq i \leq M)

1 \leq q_i \leq N (1 \leq i \leq M)

1 \leq c_i \leq 10^6 (1 \leq i \leq M)

p_i \neq q_i (1 \leq i \leq M)

Input

The input is given from Standard Input in the following format:

N M
p_1 q_1 c_1
:
p_M q_M c_M

Output

Print the minimum required fare. If it is impossible to get to station N by subway, print -1 instead.

Sample Input 1

3 3
1 2 1
2 3 1
3 1 2

Sample Output 1

1

Use company 1's lines: 1 → 2 → 3. The fare is 1 yen.

Sample Input 2

8 11
1 3 1
1 4 2
2 3 1
2 5 1
3 4 3
3 6 3
3 7 3
4 8 4
5 6 1
6 7 5
7 8 5

Sample Output 2

2

First, use company 1's lines: 1 → 3 → 2 → 5 → 6. Then, use company 5's lines: 6 → 7 → 8. The fare is 2 yen.

Sample Input 3

2 0

Sample Output 3

-1

Solution in C++14 (GCC 5.4.1) (judge verdict: Runtime Error)

#pragma once
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
#include <utility>
#include <set>
#include <cctype>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <deque>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const ll INF = 1000000007;
ll gcd(ll a, ll b) {
	if (b == 0) return a;
	return gcd(b, a % b);
}
int pr[100010];
void uini(int n) {
	for (size_t i = 0; i <= n; i++)
	{
		pr[i] = i;
	}
}

int parent(int x) {
	if (x == pr[x]) return x;
	return pr[x] = parent(pr[x]);
}

bool unit(int x, int y) {
	int px = parent(x);
	int py = parent(y);

	if (px == py) return false;
	if (px < py) {
		pr[py] = px;
	}
	else {
		pr[px] = py;
	}
	return true;
}

map<int, map<int, int>> mp;
map<int, map<int,vector<int>>> armp;

int parent(int x, int c) {
	if (mp[c][x] == 0) {
		armp[c][x].push_back(x);
		mp[c][x] = x;
		return x;
	}
	if (mp[c][x] == x) return x;
	int pi = parent(mp[c][x], c);
	vector<int> my = armp[c][x];
	std::copy(my.begin(),my.end(),std::back_inserter(armp[c][pi]));
	armp[c][x].clear();
	return mp[c][x] = pi;
}
void unite(int p, int q, int c) {
	int pp = parent(p, c);
	int qp = parent(q, c);

	if (pp < qp) {
		mp[c][qp] = pp;
		std::copy(armp[c][qp].begin(), armp[c][qp].end(), std::back_inserter(armp[c][pp]));
		armp[c][qp].clear();
	}
	else if (pp > qp) {
		mp[c][pp] = qp;
		std::copy(armp[c][pp].begin(), armp[c][pp].end(), std::back_inserter(armp[c][qp]));
		armp[c][pp].clear();
	}
}
int n, m;
map<int, map<int, int>> memo;
bool use[100010];
map<int, map<int, bool>> m2;
set<int> inner[100010];

int calc(int f,int cf) {

	if (n == f) return 0;
	int cp = parent(cf, f);
	if (memo[cp][cf] != 0) return memo[cp][cf];
	if (memo[f][cf] != 0) return memo[f][cf];
	int res = INF;
	for (auto com : inner[f]) {

		int p = parent(com, f);
		if (m2[com][p]) continue;
		m2[com][p] = true;
		vector<int> nexv = armp[com][p];
		vector<int> delc;
		int j = 0;
		for (auto nex : nexv)
		{
			if (inner[nex].size() == 1 && nex != 1 && nex != n) {
				delc.push_back(j);
			}
			if (use[nex]) continue;
			use[nex] = true;
			res = min(res, calc(nex,com) + 1);
			use[nex] = false;
			j++;
		}
		
		for (auto del : delc)
		{
			nexv.erase(nexv.begin() + del);
		}
		m2[com][p] = false;
	}

	return memo[cp][cf] = memo[f][cf] = res;
}
void solv() {
	
	cin >> n >> m;
	for (size_t i = 0; i < m; i++)
	{
		int p, q, c;
		cin >> p >> q >> c;
		if (p > q) {
			swap(p, q);
		}
		unite(p, q, c);
		inner[p].insert(c);
		inner[q].insert(c);
	}
	for (size_t i = 1; i <= n; i++)
	{
		parent(i);
	}
	use[1] = true;

	int res = calc(1,0);
	cout << (res == INF ? -1 : res) << endl;
}




int main() {
	solv();

	return 0;
}