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 LuaJIT (2.0.4) (judge verdict: Accepted)

local mma = math.max
local mfl, mce, mmi = math.floor, math.ceil, math.min
local SegForAvl = {}
local segavl_mergefunc = function(x, y)
  if x and y then return mmi(x, y)
  elseif x then return x
  elseif y then return y
  else return false end
end
SegForAvl.updateAll = function(self)
  for i = self.stagenum - 1, 1, -1 do
    for j = 1, self.cnt[i] do
      self.stage[i][j] = self.stage[i + 1][j * 2 - 1]
    end
  end
end
SegForAvl.create = function(self, n)
  local stagenum, mul = 1, 1
  self.cnt, self.stage, self.size = {1}, {{}}, {}
  while mul < n do
    mul, stagenum = mul * 2, stagenum + 1
    self.cnt[stagenum], self.stage[stagenum] = mul, {}
  end
  for i = 1, stagenum do self.size[i] = self.cnt[stagenum + 1 - i] end
  self.stagenum = stagenum
  for i = 1, mul do self.stage[stagenum][i] = i end
  self:updateAll()
end
SegForAvl.hold = function(self)
  local idx = self.stage[1][1]
  local ridx = idx
  self.stage[self.stagenum][idx] = false
  for i = self.stagenum - 1, 1, -1 do
    local dst = mce(idx / 2)
    local rem = dst * 4 - 1 - idx
    self.stage[i][dst] = segavl_mergefunc(self.stage[i + 1][idx], self.stage[i + 1][rem])
    idx = dst
  end
  return ridx
end
SegForAvl.release = function(self, idx)
  self.stage[self.stagenum][idx] = idx
  for i = self.stagenum - 1, 1, -1 do
    local dst = mce(idx / 2)
    local rem = dst * 4 - 1 - idx
    self.stage[i][dst] = segavl_mergefunc(self.stage[i + 1][idx], self.stage[i + 1][rem])
    idx = dst
  end
end
SegForAvl.new = function(n)
  local obj = {}
  setmetatable(obj, {__index = SegForAvl})
  obj:create(n)
  return obj
end

local SegAvlTree = {}
SegAvlTree.makenode = function(self, val, parent)
  local i = self.seg:hold()
  self.v[i], self.u[i], self.p[i] = val, true, parent
  self.lc[i], self.rc[i], self.l[i], self.r[i] = 0, 0, 0, 0
  return i
end
SegAvlTree.create = function(self, lessthan, n)
  self.lessthan = lessthan
  self.seg = SegForAvl.new(n)
  -- value, leftCount, rightCount, left, right, parent, used
  self.v, self.lc, self.rc, self.l, self.r, self.p, self.u = {}, {}, {}, {}, {}, {}, {}
  for i = 1, n do
    self.v[i], self.u[i], self.p[i] = 0, false, 0
    self.lc[i], self.rc[i], self.l[i], self.r[i] = 0, 0, 0, 0
  end
end

SegAvlTree.recalcCount = function(self, i)
  if self.u[i] then
    if self.u[self.l[i]] then self.lc[i] = 1 + mma(self.lc[self.l[i]], self.rc[self.l[i]])
    else self.lc[i] = 0
    end
    if self.u[self.r[i]] then self.rc[i] = 1 + mma(self.lc[self.r[i]], self.rc[self.r[i]])
    else self.rc[i] = 0
    end
  end
end
SegAvlTree.recalcCountAll = function(self, i)
  while self.u[i] do
    self:recalcCount(i)
    i = self.p[i]
  end
end

SegAvlTree.rotR = function(self, child, parent)
  local granp = self.p[parent]
  self.r[child], self.l[parent] = parent, self.r[child]
  self.p[child], self.p[parent] = granp, child
  if self.u[self.l[parent]] then self.p[self.l[parent]] = parent end
  if self.u[granp] then
    if self.l[granp] == parent then
      self.l[granp] = child
    else
      self.r[granp] = child
    end
  else
    self.root = child
  end
  self:recalcCountAll(parent)
end

SegAvlTree.rotL = function(self, child, parent)
  local granp = self.p[parent]
  self.l[child], self.r[parent] = parent, self.l[child]
  self.p[child], self.p[parent] = granp, child
  if self.u[self.r[parent]] then self.p[self.r[parent]] = parent end
  if self.u[granp] then
    if self.r[granp] == parent then
      self.r[granp] = child
    else
      self.l[granp] = child
    end
  else
    self.root = child
  end
  self:recalcCountAll(parent)
end

SegAvlTree.add = function(self, val)
  if not self.u[self.root] then self.root = self:makenode(val, 0) return end
  local pos = self.root
  local added = false
  while not added do
    if self.lessthan(val, self.v[pos]) then
      if self.u[self.l[pos]] then
        pos = self.l[pos]
      else
        self.l[pos] = self:makenode(val, pos)
        pos = self.l[pos]
        added = true
      end
    else
      if self.u[self.r[pos]] then
        pos = self.r[pos]
      else
        self.r[pos] = self:makenode(val, pos)
        pos = self.r[pos]
        added = true
      end
    end
  end
  while self.u[pos] do
    local child, parent = pos, self.p[pos]
    if not self.u[parent] then
      break
    end
    self:recalcCount(parent)
    if self.l[parent] == child then
      if self.lc[parent] - 1 == self.rc[parent] then
        pos = parent
      elseif self.lc[parent] - 2 == self.rc[parent] then
        self:recalcCount(child)
        if self.lc[child] - 1 == self.rc[child] then
          self:rotR(child, parent)
        else
          local cr = self.r[child]
          self:rotL(cr, child)
          self:rotR(cr, parent)
        end
        self:recalcCountAll(child)
        pos = nil
      else
        self:recalcCountAll(child)
        pos = nil
      end
    else -- parent.r == child
      if self.rc[parent] - 1 == self.lc[parent] then
        pos = parent
      elseif self.rc[parent] - 2 == self.lc[parent] then
        self:recalcCount(child)
        if self.rc[child] - 1 == self.lc[child] then
          self:rotL(child, parent)
        else
          local cl = self.l[child]
          self:rotR(cl, child)
          self:rotL(cl, parent)
        end
        self:recalcCountAll(child)
        pos = nil
      else
        self:recalcCountAll(child)
        pos = nil
      end
    end
  end
end

SegAvlTree.rmsub = function(self, node)
  while self.u[node] do
    self:recalcCount(node)
    if self.lc[node] == self.rc[node] then
      node = self.p[node]
    elseif self.lc[node] + 1 == self.rc[node] then
      self:recalcCountAll(self.p[node])
      node = nil
    else
      if self.lc[self.r[node]] == self.rc[self.r[node]] then
        self:rotL(self.r[node], node)
        self:recalcCountAll(node)
        node = nil
      elseif self.lc[self.r[node]] + 1 == self.rc[self.r[node]] then
        local nr = self.r[node]
        self:rotL(nr, node)
        node = nr
      else
        local nrl = self.l[self.r[node]]
        self:rotR(nrl, self.r[node])
        self:rotL(nrl, node)
        node = nrl
      end
    end
  end
end

SegAvlTree.pop = function(self)
  local node = self.root
  while self.u[self.l[node]] do
    node = self.l[node]
  end
  local v = self.v[node]
  if self.u[self.p[node]] then
    if self.u[self.r[node]] then self.p[self.r[node]] = self.p[node] end
    self.l[self.p[node]] = self.r[node]
    self:rmsub(self.p[node])
  else
    if self.r[node] then self.p[self.r[node]] = 0 end
    self.root = self.r[node]
  end
  self.seg:release(node)
  return v
end

SegAvlTree.new = function(lessthan, n)
    local obj = {}
    setmetatable(obj, {__index = SegAvlTree})
    obj:create(lessthan, n)
    return obj
end


local n, m = io.read("*n", "*n")
local ps, qs, cs = {}, {}, {}
local companies = {}
local stations = {}
for i = 1, n do
  stations[i] = {}
end
for i = 1, m do
  local p, q, c = io.read("*n", "*n", "*n")
  if not companies[c] then companies[c] = {} end
  if stations[p][c] and stations[q][c] then
    if stations[p][c] ~= stations[q][c] then
      local ci_p, ci_q = stations[p][c], stations[q][c]
      if #companies[c][ci_p] < #companies[c][ci_q] then
        for j = 1, #companies[c][ci_p] do
          local st = companies[c][ci_p][j]
          stations[st][c] = ci_q
          table.insert(companies[c][ci_q], st)
        end
        companies[c][ci_p] = {}
      else
        for j = 1, #companies[c][ci_q] do
          local st = companies[c][ci_q][j]
          stations[st][c] = ci_p
          table.insert(companies[c][ci_p], st)
        end
        companies[c][ci_q] = {}
      end
    end
  elseif not stations[p][c] and not stations[q][c] then
    table.insert(companies[c], {p, q})
    stations[p][c] = #companies[c]
    stations[q][c] = #companies[c]
  elseif stations[p][c] then
    local idx = stations[p][c]
    stations[q][c] = idx
    table.insert(companies[c][idx], q)
  else
    local idx = stations[q][c]
    stations[p][c] = idx
    table.insert(companies[c][idx], p)
  end
end
local len = {}
local asked = {}
local tasknum = 0
local done = 0
local tasktree = SegAvlTree.new(function(x, y) return len[x[1]][x[2]] < len[y[1]][y[2]] end, 200000)
for i = 1, n do
  asked[i] = false
  len[i] = {}
  for company, group in pairs(stations[i]) do
    len[i][company] = -1
  end
end
local function addtask(station, company)
  tasknum = tasknum + 1
  tasktree:add({station, company})
end
for company, group in pairs(stations[1]) do
  len[1][company] = 1
  addtask(1, company)
end
local e,f = 0,0
while done < tasknum do
  done = done + 1
  local taskidx = tasktree:pop()
  local src_station, src_company = taskidx[1], taskidx[2]
  local src_group = stations[src_station][src_company]
  local srclen = len[src_station][src_company]
  if not asked[src_station] then
    asked[src_station] = true
    for dst_company, _g in pairs(stations[src_station]) do
      if src_company ~= dst_company then
        local dstlen = len[src_station][dst_company]
        if dstlen == -1 or srclen + 1 < dstlen then
          len[src_station][dst_company] = srclen + 1
          addtask(src_station, dst_company)
        end
      end
    end
  end
  if 0 < #companies[src_company][src_group] then
    for i = 1, #companies[src_company][src_group] do
      local dst_station = companies[src_company][src_group][i]
      local dstlen = len[dst_station][src_company]
      if dstlen == -1 or srclen < dstlen then
        len[dst_station][src_company] = srclen
        addtask(dst_station, src_company)
      end
    end
    companies[src_company][src_group] = {}
  end
end
local ret = -1
local mmi = math.min
for company, group in pairs(stations[n]) do
  local dstlen = len[n][company]
  if 0 < dstlen then
    if ret == -1 then
      ret = dstlen
    else
      ret = mmi(ret, dstlen)
    end
  end
end
print(ret)