ebisukeプログラミング初心者脱出黙示録

30歳を過ぎてから始めたプログラミングと競プロの記録。Pythonで取り組んでいます。Arduinoで電子工作も

AtCoder-ABC211 D - Number of Shortest paths 【Python解答例】

f:id:ebisuke33:20210725200115p:plain


AtCoder Beginner Contest211のD問題についてPythonの解答例を記事にしていきます。
AtCoder Beginner Contest 211 - AtCoder



AtCoder Beginner Contest211 D - Number of Shortest paths

D - Number of Shortest paths

問題文

AtCoder 国には 1 から N の番号がついた N 個の都市と、1 から M の番号がついた M 個の道路があります。

道路 i を通ると都市 Ai と都市 Bi の間を双方向に 1 時間で移動することができます。

都市 1 から都市 N へ最も早く移動することができる経路は何通りありますか?
答えは非常に大きくなる可能性があるので (10^9+7) で割ったあまりを求めてください。

制約

・2 ≤ N ≤ 2×10^5
・0 ≤ M ≤ 2×10^5
・1 ≤ Ai < Bi ≤ N
・(Ai,Bi) は相異なる
・入力に含まれる値は全て整数である

解答例

import collections

n, m = map(int,input().split())

graph = [[] for _ in range(n)]
for i in range(m):
    a, b = map(int,input().split())
    graph[a-1].append(b-1)
    graph[b-1].append(a-1)

mod = 10**9 + 7

que = collections.deque()
dist = [-1] * n
cnt = [0] * n
dist[0] = 0
cnt[0] = 1
que.append(0)

while len(que) != 0:
    p = que.popleft()
    for i in graph[p]:
        if dist[i] == -1:
            dist[i] = dist[p] + 1
            que.append(i)
            cnt[i] = cnt[p]
        elif dist[i] == dist[p] + 1:
            cnt[i] += cnt[p]
            cnt[i] %= mod

print(cnt[n-1])

解説

公式解説を見て解くことができました。

幅優先探索で最短距離を表すdist配列と経路の数を表すcnt配列を更新していきます。

道路によってつながっている都市AiとBiは、隣接リストgraphとして管理しました。

distの初期条件はスタート地点のdist[0]を0とします。
cntの初期条件はスタート時点では1通りなのでcnt[0]を1としました。

この条件で幅優先探索を行います。
キューからpopした都市から遷移できる都市iが未到達の場合は、最短距離を表すdist[i]に遷移前の距離に1を足して更新します。
経路の数cntは遷移前の数と同じ値で更新しました。

遷移できる都市jが到達済みであっても、最短距離distの値が同じであればcnt[j]に遷移前の数を足し合わせることで最短経路の数を更新していきました。

幅優先探索を行うことで都市Nまでの最短経路の数cnt[n-1]が求まりますので、これを出力すればOKでした。




ABC211の関連記事はこちら
ebisuke33.hatenablog.com
ebisuke33.hatenablog.com