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# (Mono 4.6.2.0) (judge verdict: Time Limit Exceeded)

using System;
using System.Collections.Generic;
using System.Linq;
public class Heap<T>{
    private List<T> array;
    private Comparison<T> cmp;
    private int size;
    
    
    public Heap(int capacity, Comparison<T> cmp){
        this.array = new List<T>(capacity);
        this.size = 0;
        this.cmp = cmp;
    }
    public void Clear(){
        array.Clear();
        this.size = 0;
    }
    
    public bool Empty(){ return size==0; }
    protected int Parent(int i){ return (i-1)/2; }
    protected int Left(int i){ return 2*i+1; }
    protected int Right(int i){ return 2*i+2; }
    
    public T Front(){
        if(size!=0){
            return array[0];
        } else {
            return default(T);
        }
    }
    
    public void Heapify(int i){
        int l = Left(i);
        int r = Right(i);
        int largest = i;
        if(l<size && cmp(array[l], array[i]) > 0) largest = l;
        if(r<size && cmp(array[r], array[largest])>0) largest = r;
        if(largest != i){
            T tmp = array[i];
            array[i] = array[largest];
            array[largest] = tmp;
            Heapify(largest);
        } 
    }
    public T Pop(){
        if(size < 1) return default(T);
        T max = array[0];
        array[0] = array[size-1];
        size--;
        Heapify(0);
        return max;
    }
    public void Insert(T key){
        size = size + 1;
        if( array.Count < size){
            array.Add(key);
        }  else {
            array[size-1] = key;
        }
        int i = size-1;
        while(i>0 && cmp(array[Parent(i)],array[i])<0){
            T tmp = array[i];
            array[i] = array[Parent(i)];
            array[Parent(i)] = tmp;
            i = Parent(i);
        }
    }
}


public struct Z2 {
    public int x, y;
    public Z2(int x, int y){
        this.x = x;
        this.y = y;
    }
}
public struct Edge {
    public int to, cost;
    public Edge(int to, int cost){
        this.to = to;
        this.cost = cost;
    }
}
//Caution: dijkstra returns error a and b is not  connected
public class FDijkstra {
    Heap<Z2> hp;
    List<Edge>[] G;
    int[] d;
    const int INF = int.MaxValue;
    
    public FDijkstra(int maxV){
        d = new int[maxV];
        hp = new Heap<Z2>(maxV, (a,b)=>b.x-a.x);
        G = new List<Edge>[maxV];
        for(int i=0;i<maxV;i++) G[i] = new List<Edge>();
       
    }
    
    public void MakeEdge(int x, int y, int cost){
        G[x].Add(new Edge(y, cost));
        //G[y].Add(new Edge(x, cost));
    }
    
    public void Dijkstra(int s){
        hp.Clear();
        for(int i=0;i<d.Length;i++) d[i] = INF;
        d[s] = 0;
        hp.Insert(new Z2(0,s));
        while(!hp.Empty()){
            Z2 p = hp.Pop();
            int v = p.y;
            if(d[v]<p.x) continue;
            foreach(var e in G[v]){
                if(d[e.to] == INF || d[e.to]>d[v]+e.cost){
                    d[e.to] = d[v]+e.cost;
                    hp.Insert(new Z2(d[e.to],e.to));
                }
            }
        }
    }
    
    public int GetDistance(int t){
        if(d[t]==INF) throw new ArgumentException();
        return d[t];
    }
}
struct Z3 {
	public int x;
	public Z2 z;
	public Z3(int x, Z2 z){
		this.x = x; this.z = z;
	}
}
 
public class A {
	int N,M;
	Dictionary<Z2,List<Z2>> edges;
    
	
	public A(){
		edges = new Dictionary<Z2,List<Z2>>();
	}
	
	string[] Rs(){
		return Console.ReadLine().Split(' ');
	}
	public void run(){
		string[] str = Rs();
		N = int.Parse(str[0]); M = int.Parse(str[1]);
        Dictionary<Z2, int> hs = new Dictionary<Z2,int>();
        FDijkstra dij = new FDijkstra(2*(M+N));
		int cnt = 0;
        for(int i=0;i<N;i++){
            edges.Add(new Z2(i,-1), new List<Z2>());
            hs.Add(new Z2(i,-1), cnt);
            cnt++;
        }
        
        Action<Z2> g = (p1) => {
            if(!hs.ContainsKey(p1)){
                hs.Add(p1, cnt);
                cnt++;
                dij.MakeEdge(hs[p1],hs[new Z2(p1.x,-1)],0);
            }
        };
        
        Action<Z2,Z2> f = (p1,p2) => {
            Z2 ne = new Z2(p1.x, -1);
            g(p1); g(p2); g(ne);
            dij.MakeEdge(hs[p1], hs[p2], 0);
            dij.MakeEdge(hs[ne],hs[p2], 1);
        };
        
        for(int i=0;i<M;i++){
			int[] inp = Rs().Select( x => int.Parse(x)-1 ).ToArray();
            Z2 e0 = new Z2(inp[0], inp[2]), e1 = new Z2(inp[1], inp[2]);
            f(e0,e1);
            f(e1,e0);
        }
        dij.Dijkstra(0);
        Z2 end = new Z2(N-1,-1);
        try {
            int ans = dij.GetDistance(hs[end]);
            Console.WriteLine(ans);  
        } catch(Exception e){
            Console.WriteLine("-1");
        }
	}
}
 
public class Program {
	static void Main(string[] args){
		A a = new A();
		a.run();
	}
}