小橋 解説
問題 : ABC211-D
https://atcoder.jp/contests/abc211/tasks/abc211_d
https://scrapbox.io/files/610e7ed7935d5a001e07ca19.png
解説 : https://atcoder.jp/contests/abc211/editorial/2003
・最短経路を1つ求めろ --> DFS ? BFS ?
・最短経路の数を求めろ --> 全部の経路見ないといけない? --> BFS ?
DFS --> 再帰を使って実装
BFS --> キューを使って実装
〜〜実行時間の問題〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
DFSやBFSの実行時間 ーー> O(N+M) ※N=ノード(町)の数、M=辺(道)の数
今回の問題は2<N<2 * 10^5、0<M<2 * 10^5 なので 合計O(2 * 10^6) --> OK
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
幅優先のいいところ
--> DFSは後からその街へ行くための新しい最短経路が見つかる可能性がある
--> BFSは後からより早い経路が見つかることはない、前までの最短経路と同じ速さでいける経路しか見つからない
〜〜コード〜〜
code:python
N, M = map(int, input().split())
roads = []
for i in range(M):
roads.append(list(map(int, input().split())))
# ① 初めにどこからどこへ行けるかの配列(graph)を作成する
graph = []
for _ in range(N):
graph.append([])
# どこからどこにいけるかの配列(graph)を作成
for i in roads:
graph[i0-1].append(i1-1)
graph[i1-1].append(i0-1)
# ② 幅優先探索を使ってとく
que = 0 # クエリは今後見るべき点(町)を格納する配列
dist = None*N # その街へ行くまでの最短距離を格納する配列(未到達の街はNone)
dist0 = 0 # 初期値
cnt = 0*N # その街への最短経路の数を格納する配列
cnt0 = 1 # 初期値
for v in que:
for vv in graphv:
if distvv == None: # 初めてその町に到達する場合
distvv = distv + 1 # 1つ前の町までの距離+1
que.append(vv) # 次に見る町をクエリに格納
cntvv = cntv # その町までの最短到達経路数 = 1つ前の町までの最短到達経路数
elif distvv == distv+1: # すでに他のルートでこの街に到達している+そのルートと今回のルートの到達時間が同じ 場合
cntvv += cntv # その街までの最短到達経路数=別のルートの最短到達経路数+今回のルートの最短到達経路数(1つ前の町までの最短到達経路数)
cntvv %= 10**9+7 # 割ってるだけ
print(cntN-1)
入力例1に対する動作の説明
動作の例.pptx
参考:
・https://qiita.com/drken/items/996d80bcae64649a6580
・https://qiita.com/drken/items/4a7869c5e304883f539b
#勉強会
#BFS