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 Go (1.6) (judge verdict: Wrong Answer)

package main

import (
  "bufio"
  "container/heap"
  "fmt"
  "os"
  "strconv"
  "strings"
)

const INF = 1000000000

func main() {
  input := Input{bufio.NewReaderSize(os.Stdin,100)}
  n,m := input.Next2Ints()
  g := NewGraph(n+2*m)
  st := make([]map[int]int,n)
  for i:=0;i<n;i++ { st[i] = make(map[int]int) }
  k := n
  for i:=0;i<m;i++ {
    p,q,c := input.Next3Ints()
    p,q = p-1,q-1
    x,pok := st[p][c]
    y,qok := st[q][c]
    if pok && qok {
      g.Add(x,y,0)
      g.Add(y,x,0)
      continue
    }
    if !pok { x = k;st[p][c] = x;k++ }
    if !qok { y = k;st[q][c] = y;k++ }
    g.Add(x,p,0)
    g.Add(p,y,1)
    g.Add(y,q,0)
    g.Add(q,x,1)
  }
  c := g.Dijkstra(0)
  if c[n-1] == INF { c[n-1] = -1 }
  fmt.Println(c[n-1])
}

type Item struct { pos,cost,idx int }
type PriorityQueue []*Item
func(pq PriorityQueue) Len() int { return len(pq) }
func(pq PriorityQueue) Less(i,j int) bool { return pq[i].cost < pq[j].cost }
func(pq PriorityQueue) Swap(i,j int) {
  pq[i],pq[j] = pq[j],pq[i]
  pq[i].idx,pq[j].idx = i,j
}
func(pq *PriorityQueue) Push(x interface{}) {
  n := len(*pq)
  item := x.(*Item)
  item.idx = n
  *pq = append(*pq,item)
}
func(pq *PriorityQueue) Pop() interface{} {
  old := *pq
  n := len(old)
  item := old[n-1]
  item.idx = -1
  *pq = old[0:n-1]
  return item
}

type Edge struct { to,cost int }
type Graph [][]Edge
func NewGraph(n int) Graph { return make([][]Edge,n) }
func(g Graph) AddEdge(from int,e Edge) { g[from] = append(g[from],e) }
func(g Graph) Add(from,to,c int) { g.AddEdge(from,Edge{to,c}) }
func(g Graph) Dijkstra(start int) []int {
  n := len(g)
  c := make([]int,n)
  for i:=0;i<n;i++ { c[i] = INF }
  var pq PriorityQueue
  heap.Init(&pq)
  heap.Push(&pq,&Item{pos:start,cost:0})
  c[start] = 0
  for pq.Len() > 0 {
    s := heap.Pop(&pq).(*Item)
    if s.cost > c[s.pos] { continue }
    for _,e := range g[s.pos] {
      if c[e.to] > s.cost+e.cost {
        c[e.to] = s.cost+e.cost
        heap.Push(&pq,&Item{pos:e.to,cost:c[e.to]})
      }
    }
  }
  return c
}

type Input struct { reader *bufio.Reader }
func(i *Input) NextLine() string {
  var buffer []byte
  for {
    line,isPrefix,err := i.reader.ReadLine()
    if err != nil { panic(err) }
    buffer = append(buffer,line...)
    if !isPrefix { break }
  }
  return string(buffer)
}
func(i *Input) Next2Ints() (int,int) {
  s := strings.Split(i.NextLine()," ")
  x,_ := strconv.Atoi(s[0])
  y,_ := strconv.Atoi(s[1])
  return x,y
}
func(i *Input) Next3Ints() (int,int,int) {
  s := strings.Split(i.NextLine()," ")
  x,_ := strconv.Atoi(s[0])
  y,_ := strconv.Atoi(s[1])
  z,_ := strconv.Atoi(s[2])
  return x,y,z
}