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 Common Lisp (SBCL 1.1.14) (judge verdict: Time Limit Exceeded)

;; -*- coding: utf-8 -*-
(eval-when (:compile-toplevel :load-toplevel :execute)
  (defparameter OPT
    #+swank '(optimize (speed 3) (safety 2))
    #-swank '(optimize (speed 3) (safety 0) (debug 0)))
  #+swank (ql:quickload '(:cl-debug-print :fiveam))
  #-swank (set-dispatch-macro-character #\# #\> (lambda (s c p) (declare (ignore c p)) (read s nil (values) t))))
#+swank (cl-syntax:use-syntax cl-debug-print:debug-print-syntax)
#-swank (disable-debugger) ; for CS Academy

;; BEGIN_INSERTED_CONTENTS
;; DEFINE-INTEGER-PACK and DEFINE-CONS-PACK are so to say poor man's variants of
;; DEFSTRUCT. Both "structures" can only have slots of fixed unsigned
;; bytes. DEFINE-INTEGER-PACK handles the concatenated slots as UNSIGNED-BYTE
;; and DEFINE-CONS-PACK handles them as (CONS (UNSIGNED-BYTE 62) (UNSIGNED-BYTE
;; 62)).

;; Example:
;; The following form defines the type NODE as (UNSIGNED-BYTE 9):
;; (define-integer-pack node (slot1 3) (slot2 5) (slot3 1))
;; This macro in addition defines relevant utilities: NODE-SLOT1, NODE-SLOT2,
;; NODE-SLOT3, setters and getters, PACK-NODE, the constructor, and
;; WITH-UNPACKING-NODE, the destructuring-bind-style macro.
;; 
;; DEFINE-CONS-PACK is almost the same as DEFINE-INTEGER-PACK though it will be
;; suitable for the total bits in the range [63, 124].

(eval-when (:compile-toplevel :load-toplevel :execute)
  (defun %concat-name (&rest args)
    (if (cdr args)
        (format nil "~A-~A"
                (car args)
                (apply #'%concat-name (cdr args)))
        (car args)))

  (defun %concat+name+ (&rest args)
    (format nil "+~A+" (apply #'%concat-name args))))

(defmacro define-integer-pack (name &rest slot-descriptions)
  (assert slot-descriptions () "~A has no slots." name)
  (let* ((packer-name (intern (%concat-name "PACK" name)))
         (unpacker-macro-name (intern (%concat-name "WITH-UNPACKING" name)))
         (total-size 0)
         (slots (loop with position = 0
                      for (slot-name slot-size) in slot-descriptions
                      collect (progn (check-type slot-name symbol)
                                     (check-type slot-size (integer 1))
                                     (list slot-name slot-size position))
                      do (incf position slot-size)
                      finally (setq total-size position)))
         (revslots (reverse slots))
         (new-value (gensym "NEW-VALUE"))
         (tmp (gensym)))
    `(progn
       (deftype ,name () '(unsigned-byte ,total-size))
       ;; define most positive integer for every slot as constant
       ,@(loop for (slot-name slot-size _) in slots
               collect `(defconstant ,(intern (%concat+name+ "MAX" name slot-name))
                          (- (ash 1 ,slot-size) 1)))
       ;; setter and getter
       ,@(loop for (slot-name slot-size slot-position) in slots
               for accessor-name = (intern (%concat-name name slot-name))
               append `((declaim (inline ,accessor-name
                                         (setf ,accessor-name)))
                        (defun ,accessor-name (,name)
                          (declare (type ,name ,name))
                          (ldb (byte ,slot-size ,slot-position) ,name))
                        (defun (setf ,accessor-name) (,new-value ,name)
                          (declare (type ,name ,name))
                          (setf (ldb (byte ,slot-size ,slot-position) ,name) ,new-value))))
       ;; constructor
       (declaim (inline ,packer-name))
       (defun ,packer-name ,(loop for slot in slots collect (car slot))
         (declare ,@(loop for (slot-name slot-size _) in slots
                          collect `(type (unsigned-byte ,slot-size) ,slot-name )))
         (let ((,tmp ,(caar revslots)))
           (declare (type (unsigned-byte ,total-size) ,tmp))
           ,@(loop for (slot-name slot-size _) in (cdr revslots)
                   collect `(setq ,tmp (logxor ,slot-name
                                               (the (unsigned-byte ,total-size)
                                                    (ash ,tmp ,slot-size)))))
           ,tmp))
       ;; destructuring-bind-style macro
       (defmacro ,unpacker-macro-name (vars ,name &body body)
         (check-type vars list)
         (assert (= (length vars) ,(length slots)))
         `(let ((,',tmp ,,name))
            (declare (type (unsigned-byte ,,total-size) ,',tmp))
            (let* ,(loop for var in vars
                         for rest on ',slots
                         for (slot-name slot-size _) = (car rest)
                         collect `(,var
                                   (prog1 (the (unsigned-byte ,slot-size)
                                               (ldb (byte ,slot-size 0) ,',tmp))
                                     ,@(when (cdr rest)
                                         `((setq ,',tmp (ash ,',tmp ,(- slot-size))))))))
              ,@body))))))

(defstruct (queue (:constructor make-queue
                    (&optional list &aux (tail (last list)))))
  (list nil :type list)
  (tail nil :type (or null (cons t null))))

(declaim (inline enqueue))
(defun enqueue (obj queue)
  "Pushes OBJ to the end of QUEUE."
  (symbol-macrolet ((list (queue-list queue))
                    (tail (queue-tail queue)))
    (if (null list)
        (setf tail (list obj)
              list tail)
        (setf (cdr tail) (list obj)
              tail (cdr tail))))
  queue)

(declaim (inline dequeue))
(defun dequeue (queue)
  "Removes and returns the element at the front of QUEUE. Returns NIL if QUEUE
is empty."
  (pop (queue-list queue)))

(declaim (inline queue-empty-p))
(defun queue-empty-p (queue)
  (null (queue-list queue)))

(declaim (inline enqueue-front))
(defun enqueue-front (obj queue)
  "Pushes OBJ to the front of QUEUE."
  (symbol-macrolet ((list (queue-list queue))
                    (tail (queue-tail queue)))
    (if (null list)
        (setf tail (list obj)
              list tail)
        (push obj list))
    queue))

(declaim (ftype (function * (values fixnum &optional)) read-fixnum))
(defun read-fixnum (&optional (in *standard-input*))
  (declare #.OPT)
  (macrolet ((%read-byte ()
               `(the (unsigned-byte 8)
                     #+swank (char-code (read-char in nil #\Nul))
                     #-swank (sb-impl::ansi-stream-read-byte in nil #.(char-code #\Nul) nil))))
    (let* ((minus nil)
           (result (loop (let ((byte (%read-byte)))
                           (cond ((<= 48 byte 57)
                                  (return (- byte 48)))
                                 ((zerop byte) ; #\Nul
                                  (error "Read EOF or #\Nul."))
                                 ((= byte #.(char-code #\-))
                                  (setf minus t)))))))
      (declare ((integer 0 #.most-positive-fixnum) result))
      (loop
        (let* ((byte (%read-byte)))
          (if (<= 48 byte 57)
              (setq result (+ (- byte 48) (* 10 (the (integer 0 #.(floor most-positive-fixnum 10)) result))))
              (return (if minus (- result) result))))))))

(defmacro dbg (&rest forms)
  #+swank
  (if (= (length forms) 1)
      `(format *error-output* "~A => ~A~%" ',(car forms) ,(car forms))
      `(format *error-output* "~A => ~A~%" ',forms `(,,@forms)))
  #-swank (declare (ignore forms)))

(defmacro define-int-types (&rest bits)
  `(progn
     ,@(mapcar (lambda (b) `(deftype ,(intern (format nil "UINT~A" b)) () '(unsigned-byte ,b))) bits)
     ,@(mapcar (lambda (b) `(deftype ,(intern (format nil "INT~A" b)) () '(signed-byte ,b))) bits)))
(define-int-types 2 4 7 8 15 16 31 32 62 63 64)

(declaim (inline println))
(defun println (obj &optional (stream *standard-output*))
  (let ((*read-default-float-format* 'double-float))
    (prog1 (princ obj stream) (terpri stream))))

(defconstant +mod+ 1000000007)

;; Body

(define-modify-macro minf (new-value)
  (lambda (x y) (min x y)))

(define-integer-pack elm (station 20) (color 20) (dist 20))

(defun main ()
  (declare #.OPT)
  (let* ((n (read))
         (m (read))
         (graph (make-array n :element-type 'list :initial-element nil))
         (dists (make-hash-table :test #'eql :size (* 2 m)))
         (dist-seq (make-array n :element-type 'uint32 :initial-element #xffffffff))
         ;; ((station . color) . dist)
         (q (make-queue)))
    (declare (uint31 n m))
    (dotimes (i m)
      (let ((p (- (read-fixnum) 1))
            (q (- (read-fixnum) 1))
            (c (read-fixnum)))
        (push (cons q c) (aref graph p))
        (push (cons p c) (aref graph q))))
    (enqueue 0 q)
    (setf (aref dist-seq 0) 0)
    (loop until (queue-empty-p q)
          for element = (dequeue q)
          do (with-unpacking-elm (station prevcolor dist) element
               ;; (dbg station prevcolor dist)
               (when (= station (- n 1))
                 (println dist)
                 (return-from main))
               (let* ((node (pack-elm station prevcolor 0))
                      (old-dist (gethash node dists)))
                 (when (or (null old-dist)
                           (< dist (the uint31 old-dist)))
                   (setf (gethash node dists) dist)
                   (dolist (node (aref graph station))
                     (let* ((nextstop (car node))
                            (nextcolor (cdr node))
                            (nextdist (if (= nextcolor prevcolor) dist (+ dist 1))))
                       (declare (uint32 nextcolor nextdist))
                       (when (and (null (gethash node dists))
                                  (<= nextdist (aref dist-seq nextstop)))
                         (minf (aref dist-seq nextstop) nextdist)
                         (if (= nextcolor prevcolor)
                             (enqueue-front (pack-elm nextstop nextcolor nextdist) q)
                             (enqueue (pack-elm nextstop nextcolor nextdist) q)))))))))
    (println -1)))

#-swank (main)