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.Text;
using System.Linq;


class Program
{
    public void Proc()
    {
        Reader.IsDebug = false;
        int[] inpt = Reader.ReadLine().Split(' ').Select(a => int.Parse(a)).ToArray();
        this.EkiList = new Eki[inpt[0] + 1];
        for (int i = 0; i < inpt[1]; i++)
        {
            Road r = new Road(Reader.ReadLine());
            if (!this.RoadDic.ContainsKey(r.eki1))
            {
                this.RoadDic.Add(r.eki1, new Dictionary<int,List<Road>>());
            }
            if (!this.RoadDic[r.eki1].ContainsKey(r.eki2))
            {
                this.RoadDic[r.eki1].Add(r.eki2, new List<Road>());
            }
            this.RoadDic[r.eki1][r.eki2].Add(r);
            if (!this.RoadDic.ContainsKey(r.eki2))
            {
                this.RoadDic.Add(r.eki2, new Dictionary<int, List<Road>>());
            }
            if (!this.RoadDic[r.eki2].ContainsKey(r.eki1))
            {
                this.RoadDic[r.eki2].Add(r.eki1, new List<Road>());
            }
            this.RoadDic[r.eki2][r.eki1].Add(r);
        }

        Queue<int[]> taskQ = new Queue<int[]>();
        if (RoadDic.ContainsKey(1))
        {
            foreach (int next in RoadDic[1].Keys)
            {
                foreach (Road r in RoadDic[1][next])
                {
                    taskQ.Enqueue(new int[] { next, r.Rosen, 1 });
                }
            }
        }

        while (taskQ.Count > 0)
        {
            int[] task = taskQ.Dequeue();

            int pos = task[0];
            int rosen = task[1];
            int cost = task[2];
            if (this.EkiList[pos] == null)
            {
                this.EkiList[pos] = new Eki(pos);
            }
            bool mustMoveNext = false;
            if (!this.EkiList[pos].State.ContainsKey(rosen))
            {
                mustMoveNext = true;
                this.EkiList[pos].State.Add(rosen, new MapState(rosen, cost));
            }
            else if (this.EkiList[pos].State[rosen].Cost > cost)
            {
                mustMoveNext = true;
                this.EkiList[pos].State[rosen] = new MapState(rosen, cost);
            }
            if (!mustMoveNext)
            {
                continue;
            }
            if (!RoadDic.ContainsKey(pos))
            {
                continue;
            }
            foreach(int next in this.RoadDic[pos].Keys) {
                foreach (Road r in this.RoadDic[pos][next])
                {
                    int nextCost = cost;
                    if (r.Rosen != rosen)
                    {
                        nextCost++;
                    }
                    taskQ.Enqueue(new int[] { next, r.Rosen, nextCost });
                }
            }
        }

        int ans = int.MaxValue;
        int last = this.EkiList.Length - 1;
        if (this.EkiList[last] != null)
        {
            foreach (int rosen in EkiList[last].State.Keys)
            {

                ans = Math.Min(ans, EkiList[last].State[rosen].Cost);
            }
        }
        if (ans == int.MaxValue)
        {
            ans = -1;
        }
        Console.WriteLine(ans);

    
    }

    private Eki[] EkiList;
    private Dictionary<int, Dictionary<int, List<Road>>> RoadDic = new Dictionary<int, Dictionary<int, List<Road>>>();

    public class Road
    {
        public int Rosen;
        public int eki1;
        public int eki2;
        public Road(string init)
        {
            int[] inpt = init.Split(' ').Select(a => int.Parse(a)).ToArray();
            this.eki1 = inpt[0];
            this.eki2 = inpt[1];
            this.Rosen = inpt[2];
        }
    }

    public class Eki
    {
        public int Id;

        public Dictionary<int, MapState> State = new Dictionary<int, MapState>();

        public Eki(int id)
        {
            this.Id = id;
        }
    }

    public class MapState
    {
        public int Rosen;
        public int Cost;
        public MapState(int rosen, int cost)
        {
            this.Rosen = rosen;
            this.Cost = cost;
        }
    }


    public class Reader
    {
        public static bool IsDebug = true;
        private static String PlainInput = @"

2 0


";
        private static System.IO.StringReader Sr = null;
        public static string ReadLine()
        {
            if (IsDebug)
            {
                if (Sr == null)
                {
                    Sr = new System.IO.StringReader(PlainInput.Trim());
                }
                return Sr.ReadLine();
            }
            else
            {
                return Console.ReadLine();
            }
        }
    }
    static void Main()
    {
        Program prg = new Program();
        prg.Proc();
    }
}