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++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <algorithm>
#include <iterator>
#include <iostream>
//#include <iomanip>
//#include <cstring>
//#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
//#include <cmath>
//#include <set>
#include <map>
using namespace std;
#ifdef LOCAL
#define DEBUGMSG()                                                              \
{                                                                               \
    cerr << "[调试 @" << __PRETTY_FUNCTION__ << ":" << __LINE__ << "]" ;        \
}
#define DEBUGVAR(x)                                                             \
{                                                                               \
    cerr << "[调试 @" << __PRETTY_FUNCTION__ << ":" << __LINE__ << "]:" ;       \
    cerr << "([" << typeid(x).name() << "]" << #x << ")" << x << endl ;         \
}
#define DEBUGARR(l, r)                                                          \
{                                                                               \
    cerr << "[调试 @" << __PRETTY_FUNCTION__ << ":" << __LINE__ << "]:" ;       \
    copy(l, r, ostream_iterator<decltype(*l)>(cerr, " "));                      \
    cerr << endl ;                                                              \
}
#else
#define DEBUGMSG()
#define DEBUGVAR(x)
#define DEBUGARR(l, r)
#endif // LOCAL
const int MAXC = 1234567 ;

#define union _union_1337
#define ITRF itr->first
#define ITRS itr->second

typedef long long i64;

struct disjointSet
{
    int fa[MAXC];
    int son[MAXC];

    void clear(int N)
    {
        for(int i = 0; i <= N; i++)
            fa[i] = i;
    }

    int find(int x)
    {
        if(fa[x] == x)
            return x;
        return fa[x] = find(fa[x]);
    }

    void union(int x, int y)
    {
        int X = find(x), Y = find(y);
        if(X == Y)
            return;
        if(son[X] < son[Y])
            fa[X] = Y;
        else
        {
            fa[Y] = X;
            if(son[X] == son[Y])
                son[X]++;
        }
    }
}dS;

vector <pair<int, int>> G[MAXC];
vector <int> Adj[MAXC];
queue <int> q;
bool used[MAXC];
int newNo[MAXC];
int dist[MAXC];
int allocCnt;
int N, M;

void BFS()
{
    memset(dist, 0xFF, sizeof dist);
    q.push(1);
    dist[1] = 0;

    while(!q.empty())
    {
        int cur = q.front();
        q.pop();

        for(auto itr = Adj[cur].begin(); itr != Adj[cur].end(); itr++)
            if(dist[*itr] < 0)
                dist[*itr] = dist[cur]+1,
                q.push(*itr);
    }
}

int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);

    int a, b, c;
    cin >> N >> M ;
    for(int i = 1; i <= M; i++)
        cin >> a >> b >> c ,
        G[c].push_back(make_pair(a, b));

    allocCnt = N ;
    for(int k = 1; k <= MAXC; k++)
    {
        int fa;
        if(G[k].empty())
            continue;

        for(auto itr = G[k].begin(); itr != G[k].end(); itr++)
        {
            used[ITRF] = used[ITRS] = false,
            newNo[ITRF] = newNo[ITRS] = -1,
            dS.son[ITRF] = dS.son[ITRS] = 0;
            dS.fa[ITRF] = ITRF, dS.fa[ITRS] = ITRS;
        }

        for(auto itr = G[k].begin(); itr != G[k].end(); itr++)
            dS.union(ITRF, ITRS);
        for(auto itr = G[k].begin(); itr != G[k].end(); itr++)
        {
            if(!used[ITRF])
            {
                used[ITRF] = true;
                fa = dS.find(ITRF);
                if(newNo[fa] <= 0)
                    newNo[fa] = ++allocCnt;
                Adj[ITRF].push_back(newNo[fa]);
                Adj[newNo[fa]].push_back(ITRF);
            }
            if(!used[ITRS])
            {
                used[ITRS] = true;
                fa = dS.find(ITRS);
                if(newNo[fa] <= 0)
                    newNo[fa] = ++allocCnt;
                Adj[ITRS].push_back(newNo[fa]);
                Adj[newNo[fa]].push_back(ITRS);
            }
        }
    }

    BFS();

    if(dist[N] < 0)
        cout << -1 << endl;
    else
        cout << dist[N] / 2 << endl ;
}