Official

D - Number of Shortest paths Editorial by kyopro_friends


まずは頂点 \(1\) から頂点 \(N\) までの最短距離を求める問題を考えてみましょう。辺の重みが全て \(1\) であることから、この問題はBFS(幅優先探索)を用いることで \(O(N+M)\) で解くことができます。

元の問題も同様に、BFSを用いて \(O(N+M)\) で解くことができます。始点からの距離だけでなく、それを達成する経路の数も同時に計算します。

最短距離を求めるBFSでは、最短距離を表す配列を\(\text{dist}\) として

  • \(v\) から遷移できる各 \(v'\) に対して次を行う
    • \(v'\) に未到達なら \(\text{dist}[v']\)\(\text{dist}[v]+1\) に更新
    • そうでないなら何もしない

という処理をしますが、最短経路の数を表す配列 \(\text{cnt}\) を新たに用意することで、次のように更新することができます。

  • \(v\) から遷移できる各 \(v'\) に対して次を行う
    • \(v'\) に未到達なら \(\text{dist}[v']\)\(\text{dist}[v]+1\) に更新し、\(\text{cnt}[v']\)\(\text{cnt}[v]\) を代入する
    • \(v'\) に到達済みかつ \(\text{dist}[v']=\text{dist}[v]+1\) なら、\(\text{cnt}[v']\)\(\text{cnt}[v]\) を加算する
    • そうでないなら何もしない

実装例(Python)

# 入力の読み込み
N,M=map(int,input().split())
G=[[] for i in range(N)]
for i in range(M):
	A,B=map(int,input().split())
	A-=1
	B-=1
	G[A].append(B)
	G[B].append(A)

# 初期化
que=[0]
dist=[None]*N
cnt=[0]*N
dist[0]=0
cnt[0]=1

# BFS
for v in que:
	for vv in G[v]:
		if dist[vv] is None:
			dist[vv]=dist[v]+1
			que.append(vv)
			cnt[vv]=cnt[v]
		elif dist[vv]==dist[v]+1:
			cnt[vv]+=cnt[v]
			cnt[vv]%=10**9+7

print(cnt[N-1])

posted:
last update: