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;
class Solve{
    public int N;
    public int M;
    public Pair[] d;
    public Solve(){}
    public static int Main(){
        new Solve().Calc();
        return 0;
    }
    void Calc(){
        getinput();
        int[] x1 = new int[N];
        int t;
        Vertex[] x2 = new Vertex[N];
        Vertex[] station = new Vertex[N];
        List<Vertex> x = new List<Vertex>();
        Heap h;
        for(int i = 0;i < N;i++){
            x1[i] = -1;
            station[i] = new Vertex(-1,i,-1);
            x.Add(station[i]);
        }
        station[0].i = 0;
        Array.Sort(d,(a,b) => a.Compare(b));
        for(t=0;t < M-1;t++){
            int c = d[t].c;
            while (t < M-1){
                int p = d[t].p;
                int q = d[t].q;
                if(x1[p] != c){
                    x1[p] = c;
                    x2[p] = new Vertex(-1,p,c);
                    x.Add(x2[p]);
                    x2[p].addedge0(station[p]);
                    station[p].addedge1(x2[p]);
                }
                if(x1[q] != c){
                    x1[q] = c;
                    x2[q] = new Vertex(-1,q,c);
                    x.Add(x2[q]);
                    x2[q].addedge0(station[q]);
                    station[q].addedge1(x2[q]);
                }
                x2[p].addedge0(x2[q]);
                x2[q].addedge0(x2[p]);
                if(c == d[t+1].c){
                    t++;
                }
                else{
                    break;
                }
            }
        }
        if(t == M-2){
            t++;
        }
        if(t == M-1){
            int p = d[t].p;
            int q = d[t].q;
            Vertex P = new Vertex(-1,p,d[t].c);
            Vertex Q = new Vertex(-1,q,d[t].c);
            x.Add(P);
            station[p].addedge1(P);
            P.addedge0(station[p]);
            station[q].addedge1(Q);
            Q.addedge0(station[q]);
            P.addedge0(x[q]);
            Q.addedge0(x[p]);
        }
        h = new Heap(x.Count);
        h.push(station[0]);
        while(h.size > 0){
            Vertex v = h.pop();
            for(int i=0;i < v.edge0.Count;i++){
                if(v.i < v.edge0[i].i || v.edge0[i].i == -1){
                    v.edge0[i].i = v.i;
                    h.push(v.edge0[i]);
                }
            }
            for(int i=0;i < v.edge1.Count;i++){
                if(v.i + 1 < v.edge1[i].i || v.edge1[i].i == -1){
                    v.edge1[i].i = v.i + 1;
                    h.push(v.edge1[i]);
                }
            }
        }
        Console.WriteLine(x[N-1].i);
    }
    void getinput(){
        string[] str = Console.ReadLine().Split(' ');
        N = int.Parse(str[0]);
        M = int.Parse(str[1]);
        d = new Pair[M];
        for(int i = 0;i < M;i++){
            str = Console.ReadLine().Split(' ');
            d[i] = new Pair(int.Parse(str[0])-1,int.Parse(str[1])-1,int.Parse(str[2]));
        }
    }    
}
class Pair{
    public int p;
    public int q;
    public int c;
    public Pair(int i0,int j0,int k0){
        p = i0;
        q = j0;
        c = k0;
    }
    public int Compare(Pair pa){
        if(c > pa.c){
            return 1;
        }
        else if(c == pa.c){
            return 0;
        }       
        else{
            return -1;
        }
    }
}
class Vertex{
    public int i;
    public int k;
    public int c;
    public List<Vertex> edge0;
    public List<Vertex> edge1;
    public void addedge0(Vertex v){
        edge0.Add(v);
    }
    public void addedge1(Vertex v){
        edge1.Add(v);
    }
    public Vertex(int j,int b,int s){
        i = j;
        k = b;
        c = s;
        edge0 = new List<Vertex>();
        edge1 = new List<Vertex>();
    }
}
class Heap{
    public int size;
    Vertex[] obj;

    public Heap(int maxsize){
        size = 0;
        obj = new Vertex[maxsize];
    }

    public bool Compare(Vertex a,Vertex b){
        return a.i < b.i;
    }
    public void push(Vertex a){
        int i = size;
        size++;
        while(i > 0){
            int p = (i - 1)/2;
            if(Compare(obj[p],a)){
                obj[i] = a;
                break;
            }
            obj[i] = obj[p];
            i = p;
        }
        if(i == 0){
            obj[0] = a;
        }
    }
    public Vertex pop(){
        Vertex t = obj[0];
        int i = 0;
        size--;
        while(2*i+1 < size){
            int p = 2*i+1;
            if(p+1 < size && Compare(obj[p+1],obj[p])){
                p++;
            }
            if(Compare(obj[p],obj[size])){
                obj[i] = obj[p];
                i = p;
            }
            else{
                obj[i] = obj[size];
                break;
            }
        }
        if(2*i+1 >= size){
            obj[i] = obj[size];
        }
        return t;
    }
}