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: Memory Limit Exceeded)

#include<bits/stdc++.h>
using namespace std;


struct State {
	int id;
	int c;
	int cost;
	State(int aa, int bb, int cc) {
		id = aa;
		c = bb;
		cost = cc;
	}
  bool operator<( const State& right ) const {
        return cost > right.cost;
  }
};

struct Edge {
	long long to;
	int cost;
	Edge(long long a, int b) {
		to = a;
		cost = b;
	}
};

struct Data {
	int id;
	int c;
	int cost;
	bool visit;
	vector<Edge> next;
	Data(int a = -1, int b = -1, int cc = 2 << 28) {
		id = a;
		c = b;
		cost = cc;
		visit = false;
		next.reserve(100);
	}

  bool operator<( const Data& right ) const {
        return cost < right.cost;
  }
};


int main() {
	std::ios::sync_with_stdio(false);
  std::cin.tie(0);
	std::unordered_map<long long,Data> Map;
	long long PP = 1000005;
	int INF = 2 << 28;
	int N,M;
  cin >> N >> M;
	int p[M];
  int q[M];
  int c[M];
	for(int i = 0; i < M; i++) {
		cin >> p[i] >> q[i] >> c[i];
	}
	for(int i = 1; i <= N; i++) {
		Map[i * PP - 1] = Data(i,-1);
	}
	for(int I = 0; I < M; I++) {
		int P = p[I];
		int Q = q[I];
		int C = c[I];
		long long PPP = P * PP;
		long long QQQ = Q * PP;
		if(Map.find(PPP + C) == Map.end()) {
			Data tmp = Data(P,C);
			tmp.next.push_back(Edge(PPP - 1, 0));
			Map[PPP + C] = tmp;
			Map[PPP - 1].next.push_back(Edge(PPP + C,1));
		}
		if(Map.find(QQQ + C) == Map.end()) {
			Data tmp = Data(Q,C);
			tmp.next.push_back(Edge(QQQ - 1, 0));
			Map[QQQ + C] =  tmp;
			Map[QQQ - 1].next.push_back(Edge(QQQ + C,1));
		}
		Map[PPP + C].next.push_back(Edge(QQQ + C, 0));
		Map[QQQ + C].next.push_back(Edge(PPP + C, 0));

	}
	priority_queue<State> Q;
	Q.push(State(1,-1,0));
	while(!Q.empty()) {
		State pp = Q.top();
		Q.pop();
		if(pp.id == N) {
			Map[N * PP - 1].cost = pp.cost;
			break;
		}
		Data *nn =  &Map[pp.id * PP + pp.c];
		if(nn->visit) continue;
		nn->visit = true;

		int pns = nn->next.size();
		for(int i = 0; i < pns; i++) {
			Edge next = nn->next.at(i);
			Data *nextD = &Map[next.to];
			if(nextD->cost <= pp.cost + next.cost) continue;
			State st = State(nextD->id,nextD->c,pp.cost + next.cost);
			nextD->cost = pp.cost + next.cost;
			Q.push(st);
		}
	}
	Data goal = Map[N * PP - 1];
	if(goal.cost == INF) {
    cout << -1 << endl;
	}
	else {
		cout << goal.cost << endl;
	}
}