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



Sample input:
3 3
1 2 1
2 3 1
3 1 2


Sample output:
1

Submission status: Accepted

Solution code:
N, M = map(int, input().split())
ES = []
D = [{} for i in range(N)]

*parent, = range(M)
def root(x):
    if x == parent[x]:
        return x
    parent[x] = y = root(parent[x])
    return y
def unite(x, y):
    px = root(x); py = root(y)
    if px < py:
        parent[py] = px
    else:
        parent[px] = py

E = {}
for i in range(M):
    p, q, c = map(int, input().split()); p -= 1; q -= 1
    ES.append((p, q, c))
    if c in D[p]:
        unite(D[p][c], i)
    else:
        D[p][c] = i
    E.setdefault(p, set()).add(c)
    if c in D[q]:
        unite(D[q][c], i)
    else:
        D[q][c] = i
    E.setdefault(q, set()).add(c)
P = {}
for i in range(M):
    p, q, c = ES[i]
    s = P.setdefault(root(i), set())
    s.add(p); s.add(q)

from collections import deque
que = deque([(0, 0, 0)])
INF = 10**18
dist = [INF]*N
dist[0] = 0
gdist = [INF]*M

while que:
    cost, v, t = que.popleft()
    if t:
        # edge
        if gdist[v] < cost or v not in P:
            continue
        for w in P[v]:
            if cost + 1 < dist[w]:
                dist[w] = cost + 1
                que.append((cost + 1, w, 0))
    else:
        # node
        if dist[v] < cost or v not in E:
            continue
        for w in D[v].values():
            w = root(w)
            if cost < gdist[w]:
                gdist[w] = cost
                que.appendleft((cost, w, 1))

print(dist[N-1] if dist[N-1] < INF else -1)

Submission status: Runtime Error

Solution code:
from collections import defaultdict 

N,M=map(int,input().split())

if M == 0:
  print(-1)
  exit()

INF = 10**20
pqc = [tuple(map(lambda x:int(x)-1,input().split())) for _ in range(M)]
G = defaultdict(dict)
lines = [set() for _ in range(N)]
for p,q,c in pqc:
  G[(p,c)][(q,c)] = G[(q,c)][(p,c)] = 0
  lines[p].add(c)
  lines[q].add(c)
  
for v in range(N):
  if len(lines[v])>1:
    tmp = list(lines[v])
    for i in range(len(tmp)-1):
      for j in range(i+1,len(tmp)):
        G[(v,tmp[i])][(v,tmp[j])] = G[(v,tmp[j])][(v,tmp[i])] = 1
        
def dijkstra(start = 0):
    from heapq import heappop, heappush
    d = defaultdict(lambda:INF)
    d[start] = 0
    que = []
    heappush(que, (0, start))
    while que:
        p = heappop(que)
        v = p[1]
        if d[v] < p[0]: continue
        for u in G[v].keys():
            if d[u] > d[v] + G[v][u]:
                d[u] = d[v] + G[v][u]
                heappush(que, (d[u], u))
    return d
  
ans = INF
for c in lines[0]:
  d = dijkstra((0,c))
  ans = min(ans, min(d[(N-1,c2)] for c2 in lines[N-1]))
  
print(ans+1 if ans < INF else -1)

Submission status: Runtime Error

Solution code:
from collections import defaultdict 

N,M=map(int,input().split())

if M == 0:
  print(-1)
  exit()

INF = 10**20
pqc = [tuple(map(lambda x:int(x)-1,input().split())) for _ in range(N)]
G = defaultdict(dict)
lines = [set() for _ in range(N)]
for p,q,c in pqc:
  G[(p,c)][(q,c)] = G[(q,c)][(p,c)] = 0
  lines[p].add(c)
  lines[q].add(c)
  
for v in range(N):
  if len(lines[v])>1:
    tmp = list(lines[v])
    for i in range(len(tmp)-1):
      for j in range(i+1,len(tmp)):
        G[(v,tmp[i])][(v,tmp[j])] = G[(v,tmp[j])][(v,tmp[i])] = 1
        
def dijkstra(start = 0):
    from heapq import heappop, heappush
    d = defaultdict(lambda:INF)
    d[start] = 0
    que = []
    heappush(que, (0, start))
    while que:
        p = heappop(que)
        v = p[1]
        if d[v] < p[0]: continue
        for u in G[v].keys():
            if d[u] > d[v] + G[v][u]:
                d[u] = d[v] + G[v][u]
                heappush(que, (d[u], u))
    return d
  
ans = INF
for c in lines[0]:
  d = dijkstra((0,c))
  ans = min(ans, min(d[(N-1,c2)] for c2 in lines[N-1]))
  
print(ans+1 if ans < INF else -1)

Submission status: Runtime Error

Solution code:
import collections

n, m = map(int, input().split())
g = [[] for _ in range(n)]
for _ in range(m):
    p, q, c = map(lambda x:int(x) - 1, input().split())
    g[p].append((q, c))
    g[q].append((p, c))

que = collections.deque()
que.append((0, c))
cost = [float("INF")] * n
cost[0] = 0

while que:
    ps, pc = que.popleft()
    for ns, nc in g[ps]:
        if pc == nc and cost[ns] > cost[ps]:
            cost[ns] = cost[ps]
            que.appendleft((ns, nc))
        elif pc != nc and cost[ns] > cost[ps] + 1:
            cost[ns] = cost[ps] + 1
            que.append((ns, nc))

if cost[n - 1] == float("INF"):
    print(-1)
else:
    print(cost[n - 1])

Submission status: Runtime Error

Solution code:
import heapq


def dijkstra():
    dp[sup_v][0] = 1
    q = [(0, sup_v, 0)] # q = [(startからの距離, 現在地)]
    while q:
        d, v1, v2 = heapq.heappop(q)
        if dp[v1][v2] < d:
            continue
        for nxt_v1, nxt_v2, cost in graph[v1][v2]:
            if dp[v1][v2] + cost < dp[nxt_v1][nxt_v2]:
                dp[nxt_v1][nxt_v2] = dp[v1][v2] + cost
                heapq.heappush(q, (dp[nxt_v1][nxt_v2], nxt_v1, nxt_v2))


n, m = map(int, input().split())
info = [list(map(int, input().split())) for i in range(m)]
INF = 10 ** 18


sup_v = 10 ** 6
graph = {sup_v: {}}
dp = {sup_v: {}}
for a, b, c in info:
    a -= 1
    b -= 1
    if c not in graph:
        graph[c] = {}
        dp[c] = {}
    if a not in graph[c]:
        graph[c][a] = []
        graph[c][a].append((sup_v, a, 1))
        dp[c][a] = INF
    if b not in graph[c]:
        graph[c][b] = []
        graph[c][b].append((sup_v, b, 1))
        dp[c][b] = INF
    if a not in graph[sup_v]:
        graph[sup_v][a] = []
        dp[sup_v][a] = INF
    if b not in graph[sup_v]:
        graph[sup_v][b] = []
        dp[sup_v][b] = INF

    graph[c][a].append((c, b, 0))
    graph[c][b].append((c, a, 0))
    graph[sup_v][a].append((c, b, 0))
    graph[sup_v][b].append((c, a, 0))
    

dijkstra()
ans = INF
for i in dp:
    for j in dp[i]:
        if j == n - 1:
            ans = min(dp[i][j], ans)            
print(ans)

Submission status: Runtime Error

Solution code:
import heapq
import sys
from collections import defaultdict
input = sys.stdin.readline
N, M = map(int, input().split())
Rails = [[] for _ in range(N)]

def constant_factory(value): return lambda: value


def solve():
    Costs = defaultdict(constant_factory(1000000000))
    Visited = defaultdict(constant_factory(False))
    for _ in range(M):
        p, q, c = map(int, input().split())
        Rails[p-1].append((q-1, c))
        Rails[q-1].append((p-1, c))

    Q = [(0, 0, -1)]
    heapq.heapify(Q)
    while Q:
        currentCost, currentNode, currentCompany = heapq.heappop(Q)
        if not Visited[(currentNode, currentCompany)]:
            Visited[(currentNode, currentCompany)] = True
            if currentCompany == -1:
                for nextNode, nextCompany in Rails[currentNode]:
                    if not Visited[(nextNode, nextCompany)]:
                        if Costs[(nextNode, nextCompany)] > currentCost + 1:
                            Costs[(nextNode, nextCompany)] = currentCost + 1
                            heapq.heappush(Q, (currentCost + 1, nextNode, nextCompany))
            else:
                if not Visited[(currentNode, -1)]:
                    if Costs[(currentNode, -1)] > currentCost:
                        Costs[(currentNode, -1)] = currentCost
                        heapq.heappush(Q, (currentCost, currentNode, -1))
                for nextNode, nextCompany in Rails[currentNode]:
                    if nextCompany == currentCompany and not Visited[(nextNode, nextCompany)]:
                        if Costs[(nextNode, nextCompany)] > currentCost:
                            Costs[(nextNode, nextCompany)] = currentCost
                            heapq.heappush(Q, (currentCost, nextNode, nextCompany))
    minCost = Costs[(N-1, -1)]
    print(minCost if minCost < 1000000000 else -1)
	return 0
  
if __name__ == "__main__":
    solve()

Submission status: Runtime Error

Solution code:
import sys
input = sys.stdin.readline
from collections import defaultdict, deque

n, m = map(int, input().split())
G = defaultdict(set)
seen = set()
for _ in range(n):
  p, q, c = map(int, input().split())
  G[(p, c)].add(((q, c), 0))
  G[(q, c)].add(((p, c), 0))
  G[(p, c)].add(((p, -1), 0))
  G[(q, c)].add(((q, -1), 0))
  G[(p, -1)].add(((p, c), 1))
  G[(q, -1)].add(((q, c), 1))
que = deque()
que.append(((1, -1), 0))
while que:
  v, cnt = que.popleft()
  if v in seen:
    continue
  if v == (n, -1):
    print(cnt)
    exit()
  seen.add(v)
  for nv, cost in G[v]:
    if cost == 0:
      que.appendleft((nv, cnt+cost))
    else:
      que.append((nv, cnt+cost))
print(-1)

Submission status: Runtime Error

Solution code:
import sys
input = sys.stdin.readline
from collections import defaultdict, deque

n, m = map(int, input().split())
G = defaultdict(set)
seen = set()
for _ in range(n):
  p, q, c = map(int, input().split())
  G[(p, c)].add(((q, c), 0))
  G[(q, c)].add(((p, c), 0))
  G[(p, c)].add(((p, -1), 0))
  G[(q, c)].add(((q, -1), 0))
  G[(p, -1)].add(((p, c), 1))
  G[(q, -1)].add(((q, c), 1))
que = deque()
que.append(((1, -1), 0))
while que:
  v, cnt = que.popleft()
  if v in seen:
    continue
  if v == (n, -1):
    print(cnt)
    break
  seen.add(v)
  for nv, cost in G[v]:
    if cost == 0:
      que.appendleft((nv, cnt+cost))
    else:
      que.append((nv, cnt+cost))

Submission status: Runtime Error

Solution code:
input=sys.stdin.readline
from collections import defaultdict
from heapq import heappush, heappop,heappushpop,heapify
n,m = map(int, input().split())
link = defaultdict(list)
chg=10**8
for _ in range(m):
    p,q,c=map(int, input().split())
    link[p].append([p+chg*c,1])
    link[p+chg*c].append([p,1])

    link[q+chg*c].append([p+chg*c,0])
    link[p+chg*c].append([q+chg*c,0])

    link[q+chg*c].append([q,1])
    link[q].append([q+chg*c,1])

def dks(g,start):
    INF=float('inf')
    visited = set()
    hq = []
    heappush(hq, (0,start))
    while hq:
        shortest, i = heappop(hq)
        if i in visited:
            continue
        visited.add(i)
        for j, t in g[i]:
            if j in visited:
                continue
            if j==n:
                return (shortest+t)//2
            heappush(hq, (shortest + t, j))
    return -1
ans=dks(link,1)
print(ans)

Submission status: Runtime Error

Solution code:
import sys
input=sys.stdin.readline
n,m = map(int, input().split())
link = defaultdict(list)
for _ in range(m):
    p,q,c=map(int, input().split())
    p-=1
    q-=1
    c-=1
    link[(p,-1)].append([(p,c),1])
    link[(p,c)].append([(p,-1),1])
    link[(p,c)].append([(q,c),0])
    link[(q,c)].append([(p,c),0])
    link[(q,-1)].append([(q,c),1])
    link[(q,c)].append([(q,-1),1])

Submission status: Runtime Error

Solution code:
import sys
from collections import deque, defaultdict


def bfs01(s, t, links):
    q = deque([(0, s, -1)])  # cost, station, last-company
    visited = set()
    while q:
        d, v, e = q.popleft()
        if v == t:
            return d
        if (v, e) in visited:
            continue
        visited.add((v, e))
        if e == 0:
            for c, us in links[v]:
                for u in us:
                    if (u, c) in visited:
                        continue
                    q.append((d + 1, u, c))
        else:
            for u in links[v][e]:
                if (u, e) in visited:
                    continue
                q.appendleft((d, u, e))
            if (v, 0) not in visited:
                q.appendleft((d, v, 0))

    return -1


readline = sys.stdin.buffer.readline
read = sys.stdin.buffer.read

n, m = map(int, readline().split())
links = [defaultdict(set) for _ in range(n)]
pqc = list(map(int, read().split()))
for p, q, c in zip(pqc[0::3], pqc[1::3], pqc[2::3]):
    p -= 1
    q -= 1
    links[p][c].add(q)
    links[q][c].add(p)

print(bfs01(0, n - 1, links))

Submission status: Runtime Error

Solution code:
n,m=map(int,input().split())
s=[[]for i in range(n+1)]
for j in range(m):
    p,q,c=map(int,input().split())
    s[p].append([q,c])
    s[q].append([p,c])
l=[0]*(n+1)
l[1]=1
d=[[1,0,0]]
while not l[-1]:
    a,b,c=d.pop(0)
    for i,j in s[a]:
        if not l[i]:
            if j==b:
                l[i]=c
                d.insert(0,[i,b,c])
            else:
                l[i]=c+1
                d.append([i,j,c+1])
print(l[-1])

Submission status: Runtime Error

Solution code:
from collections import deque, defaultdict
import sys
input = sys.stdin.readline

N, M = map(int, input().split())
adj = [[] for _ in range(N+1)]
for _ in range(M):
    p, q, c = map(int, input().split())
    adj[p].append((q, c))
    adj[q].append((p, c))

deq = deque()
cost = [10 ** 7] * (N+1)
seen = [0] * (N+1)
prev = defaultdict(list)
deq.append(1)
cost[1] = 0
seen[1] = 1
while deq:
    v = deq.pop()
    for uc in adj[v]:
        u, c = uc
        if c in prev[v]:
            if cost[u] == cost[v]:
                cost[u] = cost[v]
                if seen[u] == 0:
                    deq.append(u)
                    seen[u] = 1
                prev[u].append(c)
            elif cost[u] > cost[v]:
                cost[u] = cost[v]
                if seen[u] == 0:
                    deq.append(u)
                    seen[u] = 1
                prev[u] = [c]
        else:
            if cost[u] > cost[v] + 1:
                cost[u] = cost[v] + 1
                if seen[u] == 0:
                    deq.appendleft(u)
                    seen[u] = 1
                prev[u].append(c)
            elif cost[u] == cost[v] + 1:
                prev[u].append(c)

print(cost[N]) if cost[N] < 10 ** 7 else print(-1)
x

Submission status: Runtime Error

Solution code:
# https://juppy.hatenablog.com/entry/2019/04/10/ARC061_-_E_%E3%81%99%E3%81%AC%E3%81%91%E5%90%9B%E3%81%AE%E5%9C%B0%E4%B8%8B%E9%89%84%E6%97%85%E8%A1%8C_-_Python_%E7%AB%B6%E6%8A%80%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0_Atcoder
# 参考にさせていただきました。

from collections import deque, defaultdict

chg = 10**6
n, m = map(int, input().split())
edges = defaultdict(set)
visited = dict()
for i in range(m):
    p, q, c = map(int, input().split())
    edges[p+c*chg].add(q+c*chg)
    edges[q+c*chg].add(p+c*chg)
    edges[p].add(p+c*chg)
    edges[q].add(q+c*chg)
    edges[p+c*chg].add(p)
    edges[q+c*chg].add(q)
    visited[p] = False
    visited[q] = False
    visited[p+c*chg] = False
    visited[q+c*chg] = False

ans = float("inf")
que = deque()
# now, dist
que.append((1, 0))
# 今求めるのはendの距離だけなので、dist配列はいらない
# さらに、距離は0/1なのでheapで辺を管理する必要もなく、0なら最短確定なので先に、1ならその時点での最長なので後ろにすれば良い
while que:
    now, dist = que.popleft()
    if visited[now]:
        continue
    visited[now] = True
    if now == n:
        ans = dist
        break
    for to in edges[now]:
        # 駅→ホーム
        if now < chg and to > chg:
            que.append((to, dist+1))
        else:
            que.appendleft((to, dist))
if ans == float("inf"):
    print(-1)
else:
    print(ans)

Submission status: Runtime Error

Solution code:
from collections import*
from heapq import*
def dijkstra(s):
  d=[inf]*n
  used=[True]*n
  d[s]=0
  used[s]=False
  edgelist=[]
  for e in edge[s]:
    heappush(edgelist,e)
  while len(edgelist):
    minedge=heappop(edgelist)
    if not used[minedge[1]]:
      continue
    v=minedge[1]
    d[v]=minedge[0]
    used[v]=False
    for e in edge[v]:
      if used[e[1]]:
        heappush(edgelist,(e[0]+d[v],e[1]))
  return d
inf=10**18
n,m,*t=map(int,open(0).read().split())
e=defaultdict(list)
s=set()
l=set()
f=False
for a,b,c in zip(t[::3],t[1::3],t[2::3]):
  if b<a:a,b=b,a
  if a<2 or b<2:f=True
  x,y=a+-~n*c,b+-~n*c
  if b==n:l|={y}
  e[a].append((1,x))
  e[b].append((1,y))
  e[x].extend([(0,a),(0,y)])
  e[y].extend([(0,b),(0,x)])
  s|=set((a,b,x,y))
if not f:
  print(-1)
  exit()
d={i:v for v,i in enumerate(sorted(s))}
n=len(d)
edge=tuple([]for _ in range(n))
for i in e:
  edge[d[i]].extend([(c,d[j])for c,j in e[i]])
a=dijkstra(0)
a=min(a[d[i]]for i in l)
print([a,-1][a==inf])

Submission status: Runtime Error

Solution code:
from collections import*
from heapq import*
def dijkstra(s):
  d=[inf]*n
  used=[True]*n
  d[s]=0
  used[s]=False
  edgelist=[]
  for e in edge[s]:
    heappush(edgelist,e)
  while len(edgelist):
    minedge=heappop(edgelist)
    if not used[minedge[1]]:
      continue
    v=minedge[1]
    d[v]=minedge[0]
    used[v]=False
    for e in edge[v]:
      if used[e[1]]:
        heappush(edgelist,(e[0]+d[v],e[1]))
  return d
inf=10**18
n,m,*t=map(int,open(0).read().split())
e=defaultdict(list)
s=[]
l=[]
f=False
for a,b,c in zip(t[::3],t[1::3],t[2::3]):
  if b<a:a,b=b,a
  if a<2 or b<2:f=True
  x,y=a+-~n*c,b+-~n*c
  if b==n:l.append(y)
  e[a].append((1,x))
  e[b].append((1,y))
  e[x].extend([(0,a),(0,y)])
  e[y].extend([(0,b),(0,x)])
  s.extend([a,b,x,y])
if not f:
  print(-1)
  exit()
d={i:v for v,i in enumerate(sorted(set(s)))}
n=len(d)
edge=tuple([]for _ in range(n))
for i in e:
  edge[d[i]].extend([(c,d[j])for c,j in e[i]])
a=dijkstra(0)
a=min(a[d[i]]for i in l)
print([a,-1][a==inf])

Submission status: Runtime Error

Solution code:
from collections import*
from heapq import*
def dijkstra(s):
  d=[inf]*n
  used=[True]*n
  d[s]=0
  used[s]=False
  edgelist=[]
  for e in edge[s]:
    heappush(edgelist,e)
  while len(edgelist):
    minedge=heappop(edgelist)
    if not used[minedge[1]]:
      continue
    v=minedge[1]
    d[v]=minedge[0]
    used[v]=False
    for e in edge[v]:
      if used[e[1]]:
        heappush(edgelist,(e[0]+d[v],e[1]))
  return d
inf=10**18
n,m,*t=map(int,open(0).read().split())
e=defaultdict(list)
s=[]
l=[]
f=False
for a,b,c in zip(t[::3],t[1::3],t[2::3]):
  if b<a:a,b=b,a
  if a<2 or b<2:f=True
  x,y=a+-~n*c,b+-~n*c
  if b==n:l.append(y)
  e[a].append((1,x))
  e[b].append((1,y))
  e[y].append((0,b))
  e[x].append((0,y))
  s.extend([a,b,x,y])
if not f:
  print(-1)
  exit()
d={i:v for v,i in enumerate(sorted(set(s)))}
n=len(d)
edge=tuple([]for _ in range(n))
for i in e:
  edge[d[i]].extend([(c,d[j])for c,j in e[i]])
a=dijkstra(0)
a=min(a[d[i]]for i in l)
print([a,-1][a==inf])

Submission status: Runtime Error

Solution code:
from collections import*
from heapq import*
def dijkstra(s):
  d=[inf]*n
  used=[True]*n
  d[s]=0
  used[s]=False
  edgelist=[]
  for e in edge[s]:
    heappush(edgelist,e)
  while len(edgelist):
    minedge=heappop(edgelist)
    if not used[minedge[1]]:
      continue
    v=minedge[1]
    d[v]=minedge[0]
    used[v]=False
    for e in edge[v]:
      if used[e[1]]:
        heappush(edgelist,(e[0]+d[v],e[1]))
  return d
inf=10**18
n,m,*t=map(int,open(0).read().split())
e=defaultdict(list)
s=[]
l=[]
f=False
for a,b,c in zip(t[::3],t[1::3],t[2::3]):
  if b<a:a,b=b,a
  if a<2:f=True
  x,y=a+-~n*c,b+-~n*c
  if b==n:l.append(y)
  e[a].append((1,x))
  e[y].append((0,b))
  e[x].append((0,y))
  s.extend([a,b,x,y])
if not f:
  print(-1)
  exit()
d={i:v for v,i in enumerate(sorted(set(s)))}
n=len(d)
edge=tuple([]for _ in range(n))
for i in e:
  edge[d[i]].extend([(c,d[j])for c,j in e[i]])
a=dijkstra(0)
a=min(a[d[i]]for i in l)
print([a,-1][a==inf])

Submission status: Runtime Error

Solution code:
from collections import*
from heapq import*
def dijkstra(s):
  d=[inf]*n
  used=[True]*n
  d[s]=0
  used[s]=False
  edgelist=[]
  for e in edge[s]:
    heappush(edgelist,e)
  while len(edgelist):
    minedge=heappop(edgelist)
    if not used[minedge[1]]:
      continue
    v=minedge[1]
    d[v]=minedge[0]
    used[v]=False
    for e in edge[v]:
      if used[e[1]]:
        heappush(edgelist,(e[0]+d[v],e[1]))
  return d
inf=10**18
n,m,*t=map(int,open(0).read().split())
if m<1:
  print(-1)
  exit()
e=defaultdict(list)
s=[]
l=[]
for a,b,c in zip(t[::3],t[1::3],t[2::3]):
  if b<a:a,b=b,a
  if b==n:l.append(b+n*c)
  e[a].append((1,a+n*c))
  e[b+n*c].append((0,b))
  e[a+n*c].append((0,b+n*c))
  s.extend([a,b,a+n*c,b+n*c])
d={i:v for v,i in enumerate(sorted(set(s)))}
n=len(d)
edge=tuple([]for _ in range(n))
for i in e:
  edge[d[i]].extend([(c,d[j])for c,j in e[i]])
a=dijkstra(0)
a=min(a[d[i]]for i in l)
print([a,-1][a==inf])

Submission status: Runtime Error

Solution code:
from collections import*
from heapq import*
def dijkstra(s):
  d=[float('inf')]*n
  used=[True]*n
  d[s]=0
  used[s]=False
  edgelist=[]
  for e in edge[s]:
    heappush(edgelist,e)
  while len(edgelist):
    minedge=heappop(edgelist)
    if not used[minedge[1]]:
      continue
    v=minedge[1]
    d[v]=minedge[0]
    used[v]=False
    for e in edge[v]:
      if used[e[1]]:
        heappush(edgelist,(e[0]+d[v],e[1]))
  return d
n,m,*t=map(int,open(0).read().split())
if m<1:
  print(-1)
  exit()
e=defaultdict(list)
s=[]
l=[]
for a,b,c in zip(t[::3],t[1::3],t[2::3]):
  if b<a:a,b=b,a
  if b==n:l.append(b+n*c)
  e[a].append((1,a+n*c))
  e[b+n*c].append((0,b))
  e[a+n*c].append((0,b+n*c))
  s.extend([a,b,a+n*c,b+n*c])
d={i:v for v,i in enumerate(sorted(set(s)))}
n=len(d)
edge=tuple([]for _ in range(n))
for i in e:
  edge[d[i]].extend([(c,d[j])for c,j in e[i]])
a=dijkstra(0)
a=min(a[d[i]]for i in l)
print([a,-1][a==float('inf')])

Submission status: Runtime Error

Solution code:
import sys
from collections import deque
N, M = map(int, input().split())
Edge = [[] for _ in range(N+1)]
comp = set()
for _ in range(M):
    p, q, c = map(int, sys.stdin.readline().split())
    Edge[p].append((q, c))
    Edge[q].append((p, c))
    comp.add(c)
dist = {(1, 0): 0}
Q = deque()
Q.append((1, 0))
visited = set()
while Q:
    vn, cp = Q.pop()
    if (vn, cp) in visited:
        continue
    visited.add((vn, cp))
    for vf, cf in Edge[vn]:
        if (vf, cp) in visited:
        continue
        if cp == cf:
            dist[(vf, cf)] = min(dist.get((vf, cf), 10**9), dist.get((vn, cp), 10**9))
            Q.append((vf, cf))
        else:
            dist[(vf, cf)] = min(dist.get((vf, cf), 10**9), 1 + dist.get((vn, cp), 10**9))
            Q.appendleft((vf, cf))
L = [dist.get((N, c), 10**9) for c in comp]
if not L or min(L) == 10**9:
    print(-1)
else:
    print(min(L))

Submission status: Runtime Error

Solution code:
import sys
from collections import deque
N, M = map(int, input().split())
Edge = [[] for _ in range(N+1)]
comp = set()
for _ in range(M):
    p, q, c = map(int, sys.stdin.readline().split())
    Edge[p].append((q, c))
    Edge[q].append((p, c))
    comp.add(c)
dist = {(1, 0): 0}
Q = deque()
Q.append((1, 0))
visited = set()
while Q:
    vn, cp = Q.pop()
    if (vn, cp) in visited:
        continue
    visited.add((vn, cp))
    for vf, cf in Edge[vn]:
        if cp == cf:
            dist[(vf, cf)] = min(dist.get((vf, cf), float('inf')), dist.get((vn, cp), float('inf')))
            Q.append((vf, cf))
        else:
            dist[(vf, cf)] = min(dist.get((vf, cf), float('inf')), 1 + dist.get((vn, cp), float('inf')))
            Q.appendleft((vf, cf))

print(min([dist.get((N, c), float('inf')) for c in comp]))

Submission status: Runtime Error

Solution code:
import sys
stdin = sys.stdin
 
sys.setrecursionlimit(10**7) 
 
def li(): return map(int, stdin.readline().split())
def li_(): return map(lambda x: int(x)-1, stdin.readline().split())
def lf(): return map(float, stdin.readline().split())
def ls(): return stdin.readline().split()
def ns(): return stdin.readline().rstrip()
def lc(): return list(ns())
def ni(): return int(stdin.readline())
def nf(): return float(stdin.readline())

from heapq import heappush, heappop

def dijkstra(graph: list, start, INF, num2node, destination) -> int:
    n = len(graph)
    dist = [INF]*n
    visited = [False]*n
    
    dist[start] = 0
    que = [(dist[start], start)]
    
    while que:
        cost, cur = heappop(que)
        
        if visited[cur]:
            continue
        
        if num2node[cur][0] == destination:
            return cost
        
        visited[cur] = True
        
        for nextnode, edgecost in graph[cur]:
            nextcost = cost + edgecost
            if nextcost < dist[nextnode]:
                dist[nextnode] = nextcost
                heappush(que, (nextcost, nextnode))
      
    return INF

def get_nodenum(station, company, keyset, node2num):
    if (station, company) not in keyset:
        keyset.add((station, company))
        keyslen = len(keyset)-1
        node2num.update({(station, company): keyslen})
        
        return keyslen
    
    else:
        return node2num[(station, company)]
    

n,m = li()

graph = [[] for _ in [0]*(5*(10**5))]
node2num = {}
num2node = {}
keyset = set()

for _ in range(m):
    p,q,c = li()

    # ノードの登録
    pc_nodenum = get_nodenum(p,c,keyset,node2num)
    qc_nodenum = get_nodenum(q,c,keyset,node2num)
    
    pz_nodenum = get_nodenum(p,0,keyset,node2num)
    qz_nodenum = get_nodenum(q,0,keyset,node2num)
    

    # 隣接リストの更新
    graph[pc_nodenum].append((qc_nodenum, 0))
    graph[qc_nodenum].append((pc_nodenum, 0))
    
    graph[pc_nodenum].append((pz_nodenum, 0))
    graph[qc_nodenum].append((qz_nodenum, 0))
    
    graph[pz_nodenum].append((pc_nodenum, 1))
    graph[qz_nodenum].append((qc_nodenum, 1))
    
num2node = {ni: (stati, compi) for (stati, compi), ni in node2num.items()}

INF = 1<<62
start = get_nodenum(1, 0, keyset, node2num)
ans = dijkstra(graph, start, INF, num2node, n)

print(-1 if ans == INF else ans)

Submission status: Runtime Error

Solution code:
import sys
stdin = sys.stdin
 
sys.setrecursionlimit(10**7) 
 
def li(): return map(int, stdin.readline().split())
def li_(): return map(lambda x: int(x)-1, stdin.readline().split())
def lf(): return map(float, stdin.readline().split())
def ls(): return stdin.readline().split()
def ns(): return stdin.readline().rstrip()
def lc(): return list(ns())
def ni(): return int(stdin.readline())
def nf(): return float(stdin.readline())

from heapq import heappush, heappop

def dijkstra(graph: list, start, INF=float('inf')) -> list:
    n = len(graph)
    dist = [INF]*n
    visited = [False]*n
    
    dist[start] = 0
    que = [(dist[start], start)]
    
    while que:
        cost, cur = heappop(que)
        
        if visited[cur]:
            continue
        
        visited[cur] = True
        
        for nextnode, edgecost in graph[cur]:
            nextcost = cost + edgecost
            if nextcost < dist[nextnode]:
                dist[nextnode] = nextcost
                heappush(que, (nextcost, nextnode))
      
    return dist

def get_nodenum(station, company, keyset, node2num):
    if (station, company) not in keyset:
        keyset.add((station, company))
        keyslen = len(keyset)-1
        node2num.update({(station, company): keyslen})
        
        return keyslen
    
    else:
        return node2num[(station, company)]
    

n,m = li()

graph = [[] for _ in range(3*(10**5))]
node2num = {}
num2node = {}
keyset = set()

start = -1

for _ in range(m):
    p,q,c = li()

    # ノードの登録
    pc_nodenum = get_nodenum(p,c,keyset,node2num)
    qc_nodenum = get_nodenum(q,c,keyset,node2num)
    
    pz_nodenum = get_nodenum(p,0,keyset,node2num)
    qz_nodenum = get_nodenum(q,0,keyset,node2num)
    

    # 隣接リストの更新
    graph[pc_nodenum].append((qc_nodenum, 0))
    graph[qc_nodenum].append((pc_nodenum, 0))
    
    graph[pc_nodenum].append((pz_nodenum, 0))
    graph[qc_nodenum].append((qz_nodenum, 0))
    
    graph[pz_nodenum].append((pc_nodenum, 1))
    graph[qz_nodenum].append((qc_nodenum, 1))
    
num2node = {ni: (stati, compi) for (stati, compi), ni in node2num.items()}

INF = 1<<62
ans = INF

start = get_nodenum(1, 0, keyset, node2num)

dist = dijkstra(graph, start, INF)
for nodei in range(len(keyset)):
    if num2node[nodei][0] == n:
        ans = min(ans, dist[nodei])
        
print(-1 if ans == INF else ans)