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: Wrong Answer)

using System;
using System.Collections.Generic;


//max heap
public class Heap<T>{
    private List<T> array;
    private IComparer<T> cmp;
    private int size;
    
    
    
    
    public Heap(int capacity, IComparer<T> cmp){
        this.array = new List<T>(capacity);
        this.size = 0;
        this.cmp = cmp;
    }
    
    //Caution:subeffetable!!
    public Heap(List<T> array, IComparer<T> cmp){
        this.array = array;
        this.cmp = cmp;
        this.size = array.Count;
        BuildHeap();
    }
    
    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.Compare(array[l], array[i]) > 0) largest = l;
        if(r<size && cmp.Compare(array[r], array[largest])>0) largest = r;
        if(largest != i){
            T tmp = array[i];
            array[i] = array[largest];
            array[largest] = tmp;
            Heapify(largest);
        } 
    }
    
    public void BuildHeap(){
        for(int i= (size-2)/2; i>-1;--i){
            Heapify(i);
        }
    }
    
    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.Compare(array[Parent(i)],array[i])<0){
            T tmp = array[i];
            array[i] = array[Parent(i)];
            array[Parent(i)] = tmp;
            i = Parent(i);
        }
    }
    
    public void Print(){
        for(int i=0;i<size;i++){
            Console.Write(array[i]);
        }
        Console.WriteLine();
    }
}
class Cmp : Comparer<Z3> {
    public override int Compare(Z3 x, Z3 y){
        if(x.x<y.x) return 1;
        if(x.x>y.x) return -1;
        return 0;
    }
}

public struct Z3 {
    public int x, y, z;
    public Z3(int x, int y, int z){
        this.x = x;
        this.y = y;
        this.z = z;
    }
}
public struct Edge {
    public int to, cost;
    public Edge(int to, int cost){
        this.to = to;
        this.cost = cost;
    }
}

public class FDijkstra {
    Heap<Z3> hp;
    List<Edge>[] G;
    int[] d;
    const int INF = int.MaxValue;
    
    public FDijkstra(int maxV){
        d = new int[maxV];
        hp = new Heap<Z3>(maxV, new Cmp());
        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 Z3(0,s,-1));
        while(!hp.Empty()){
            Z3 p = hp.Pop();
            int v = p.y;
            if(d[v]<p.x) continue;
            foreach(var e in G[v]){
                int nc = d[v] + (e.cost==p.z?0:1);
                if(d[e.to]>nc){
                    d[e.to] = nc;
                    hp.Insert(new Z3(d[e.to],e.to,e.cost));
                }
            }
        }
    }
    
    public int GetDistance(int t){
        return d[t];
    }
}


public class Program {
    static void Main(string[] args){
        string[] str = Console.ReadLine().Split(' ');
        int N = int.Parse(str[0]);
        int M = int.Parse(str[1]);
        FDijkstra fd = new FDijkstra(N);
        for(int i=0;i<M;i++){
            str = Console.ReadLine().Split(' ');
            fd.MakeEdge(int.Parse(str[0])-1, int.Parse(str[1])-1, int.Parse(str[2]));
        }
        
        fd.Dijkstra(0);
        int ans = fd.GetDistance(N-1);
        if(ans==int.MaxValue){
            ans = -1;
        }
        Console.WriteLine(ans);
    }
}