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 Java8 (OpenJDK 1.8.0) (judge verdict: Time Limit Exceeded)

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;
 
public class Main {
	
	public static void main(String[] args) throws IOException {
		final Scanner sc = new Scanner(System.in);
		
		final int N = sc.nextInt();
		final int M = sc.nextInt();
		
		ArrayList<HashMap<Integer, HashSet<Integer>>> adj_list = new ArrayList<HashMap<Integer, HashSet<Integer>>>();
		for(int i = 0; i < N; i++){
			adj_list.add(new HashMap<Integer, HashSet<Integer>>());
		}
		
		for(int i = 0; i < M; i++){
			final int p = sc.nextInt() - 1;
			final int q = sc.nextInt() - 1;
			final int c = sc.nextInt();
			
			if(!adj_list.get(p).containsKey(q)){
				adj_list.get(p).put(q, new HashSet<Integer>());
			}
			adj_list.get(p).get(q).add(c);
			
			if(!adj_list.get(q).containsKey(p)){
				adj_list.get(q).put(p, new HashSet<Integer>());
			}
			adj_list.get(q).get(p).add(c);
		}
		
		//System.out.println(adj_list);
		
		long[] min_cost = new long[N];
		Arrays.fill(min_cost, Long.MAX_VALUE);
		min_cost[0] = 0;
		
		LinkedList<Integer> queue = new LinkedList<Integer>();
		queue.add(0);
		queue.add(-1);
		
		while(!queue.isEmpty()){
			final int curr = queue.poll();
			final int prev_company = queue.poll();
			
			
			for(final Entry<Integer, HashSet<Integer>> entry : adj_list.get(curr).entrySet()){
				final int next = entry.getKey();
				//System.out.println(next);
				
				for(final int company : entry.getValue()){
					final long next_cost = min_cost[curr] + (prev_company == company ? 0 : 1);
					
					if(min_cost[next] < next_cost){ continue; }
					
					if(prev_company == company){
						min_cost[next] = next_cost;
						queue.addFirst(company);
						queue.addFirst(next);
					}else{
						min_cost[next] = Math.min(min_cost[next], next_cost);
						queue.addLast(next);
						queue.addLast(company);
					}
				}
			}
		}
		
		System.out.println(min_cost[N - 1] == Long.MAX_VALUE ? -1 : min_cost[N - 1]);
	}
 
	public static class Scanner implements Closeable {
		private BufferedReader br;
		private StringTokenizer tok;
 
		public Scanner(InputStream is) throws IOException {
			br = new BufferedReader(new InputStreamReader(is));
		}	
 
		private void getLine() throws IOException {
			while (!hasNext()) {
				tok = new StringTokenizer(br.readLine());
			}
		}
 
		private boolean hasNext() {
			return tok != null && tok.hasMoreTokens();
		}
 
		public String next() throws IOException {
			getLine();
			return tok.nextToken();
		}
 
		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}
 
		public long nextLong() throws IOException {
			return Long.parseLong(next());
		}
 
		public double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}
 
		public void close() throws IOException {
			br.close();
		}
	}
}