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 Java7 (OpenJDK 1.7.0) (judge verdict: Wrong Answer)

import java.io.*;
import java.util.*;


public class Main {

	public static void main(String[] args) throws Exception {
		int i;
		int N, M;
		int p, q, c;
		Dijkstra<Pair<Integer, Integer>> dijkstra = new Dijkstra<Pair<Integer, Integer>>();
		Pair<Integer, Integer> pc;
		Pair<Integer, Integer> qc;
		Pair<Integer, Integer> outside;
		Set<Integer> taboo = new HashSet<Integer>();

		FastScanner fs = new FastScanner();

		N = fs.nextInt();
		M = fs.nextInt();

		if(M == 0) {
			System.out.println(-1);
			return;
		}

		for(i=0;i<M;i++) {
			p = fs.nextInt(); q = fs.nextInt(); c = fs.nextInt();
			pc = new Pair<Integer, Integer>(p, c);
			qc = new Pair<Integer, Integer>(q, c);
			dijkstra.input(pc, qc, 0, true);
			if(!taboo.contains(p)) {
				outside = new Pair<Integer, Integer>(p, -1);
				dijkstra.input(pc, outside, 0, false);
				dijkstra.input(outside, pc, 1, false);
			}
			if(!taboo.contains(q)) {
				outside = new Pair<Integer, Integer>(q, -1);
				dijkstra.input(qc, outside, 0, false);
				dijkstra.input(outside, qc, 1, false);
			}
		}

		Pair<Integer, Integer> sp = new Pair<Integer, Integer>(1, -1);
		Pair<Integer, Integer> ep = new Pair<Integer, Integer>(N, -1);
		Pair<Integer, Pair<Integer, Integer>> ans = dijkstra.solve(sp, ep, Math.max(N, M)/5);

		if(ans.second == null) {
			System.out.println(-1);
		} else {
			if(ans.first < 0) {
				System.out.println(-1);
			} else {
				System.out.println(ans.first);
			}
		}

		//System.out.println(dijkstra.inputCallCount + ": " + dijkstra.inputTime/1000000 + "ms");
	}
}

class FastScanner {
    private final InputStream in = System.in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int buflen = 0;
    private boolean hasNextByte() {
        if (ptr < buflen) {
            return true;
        }else{
            ptr = 0;
            try {
                buflen = in.read(buffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (buflen <= 0) {
                return false;
            }
        }
        return true;
    }
    private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
    private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
    public boolean hasNext() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++; return hasNextByte();}
    public String next() {
        if (!hasNext()) throw new NoSuchElementException();
        StringBuilder sb = new StringBuilder();
        int b = readByte();
        while(isPrintableChar(b)) {
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }
    public long nextLong() {
        if (!hasNext()) throw new NoSuchElementException();
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while(true){
            if ('0' <= b && b <= '9') {
                n *= 10;
                n += b - '0';
            }else if(b == -1 || !isPrintableChar(b)){
                return minus ? -n : n;
            }else{
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }
    public int nextInt() {
        long nl = nextLong();
        if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) throw new NumberFormatException();
        return (int) nl;
    }
    public double nextDouble() { return Double.parseDouble(next());}
}

class Dijkstra<E> {
	HashMap<E, Integer> d = new HashMap<E, Integer>();
	HashMap<E, E> prev = new HashMap<E, E>();
	PriorityQueue<Pair<E, Integer>> Q = new PriorityQueue<Pair<E, Integer>>(1000000,
			new Comparator<Pair<E, Integer>>() {
				@Override
				public int compare(Pair<E, Integer> o1, Pair<E, Integer> o2) {
					if(o1.second < o2.second) return -1;
					else if(o1.second > o2.second) return 1;
					else {
						if(o1.equals(o2)) return 0;
						else return 1;
					}
				}
			});
	HashMap<E, HashMap<E, Integer>> list = new HashMap<E, HashMap<E, Integer>>();

	Dijkstra() {

	}

	public long inputTime = 0;
	public long inputCallCount = 0;

	void input(E u, E v, int cost, boolean isDig) {
		//inputCallCount++;
		//long s = System.nanoTime();
		if(!list.containsKey(u)) {
			list.put(u, new HashMap<E, Integer>());
			d.put(u, Integer.MAX_VALUE);
			prev.put(u, null);
			Q.add(new Pair<E, Integer>(u, d.get(u)));
		}
		list.get(u).put(v, cost);

		if(isDig) {
			if(!list.containsKey(v)) {
				list.put(v, new HashMap<E, Integer>());
				d.put(v, Integer.MAX_VALUE);
				prev.put(v, null);
				Q.add(new Pair<E, Integer>(v, d.get(v)));
			}
			list.get(v).put(u, cost);
		}
		//long e = System.nanoTime();
		//inputTime += (e - s);
	}

	Pair<Integer, E> solve(E start, E end, int limit) {
		int count = 0;
		d.put(start, 0);
		Q.remove(start);
		Q.add(new Pair<E, Integer>(start, d.get(start)));

		while(!Q.isEmpty() && count < limit) {
			//E u = Q.pollFirst().first;
			E u = Q.poll().first;
			int alt;
			for(E v : list.get(u).keySet()) {
				alt = d.get(u) + list.get(u).get(v);
				if(d.get(v) > alt) {
					d.put(v, alt);
					prev.put(v, u);
					Q.add(new Pair<E, Integer>(v, alt));
				}
			}
			count++;
		}

		return new Pair<Integer, E>(d.get(end), prev.get(end));
	}
}

class Pair<F, S> {
    public final F first;
    public final S second;

    Pair (F first, S second) {
        this.first = first;
        this.second = second;
    }

    @Override
    public boolean equals (Object obj) {
        if (! (obj instanceof Pair))
            return false;
        @SuppressWarnings("unchecked")
		Pair<F, S> pair = (Pair<F, S>) obj;
        return (first.equals (pair.first) && second.equals (pair.second));
    }

    @Override
    public int hashCode () {
        return first.hashCode () ^ second.hashCode ();
    }

    @Override
    public String toString() {
    	return "(" + first.toString() + "," + second.toString() + ")";
    }
}