Dial’s Algorithm
概要
単一始点最短経路問題(SSSP)を解くアルゴリズム。
コストごとにbucketを用意し、コストが小さい順にbucketに含まれる頂点から探索する。
各bucketでは頂点をDoubly Linked Listで管理し、頂点のコストが更新された時に追加削除を \(O(1)\) でできるようにする。
辺のコストが小さい場合に高速になる。
計算量
グラフ \(G = (V, E)\) に含まれる辺の最大コストを \(W\) とすると \(O(|E| + W |V|)\)
実装
# - N頂点のグラフG
# - 辺の重みは最大W
# - 開始頂点はs
def dial(N, G, W, s):
B = [-1]*(N*W + 1) # first
L = [-1]*(N*W + 1) # last
# prv, nxt: 各頂点の前後を管理
*prv, = range(-1, N-1)
*nxt, = range(1, N+1)
nxt[-1] = -1
prv[s+1] = s-1
nxt[s-1] = (s+1 if s < N-1 else -1)
prv[s] = nxt[s] = -1
B[0] = L[0] = s
B[N*W] = +(s == 0)
L[N*W] = (N-1 if s < N-1 else N-2)
dist = [N*W] * N
dist[s] = 0
for w in range(N*W):
v = B[w]
while v != -1:
for x, c in G[v]:
e = w + c
if e < dist[x]:
d = dist[x]
dist[x] = e
# bucket d から 頂点x を削除
p = prv[x]; n = nxt[x]
if p != -1:
nxt[p] = n
else:
B[d] = n
if n != -1:
prv[n] = p
else:
L[d] = p
# bucket e の末尾に 頂点x を追加
l = L[e]
if l != -1:
nxt[l] = x
else:
B[e] = x
prv[x] = l; nxt[x] = -1
L[e] = x
v = nxt[v]
return dist
Verified
-
AOJ: "ALDS1_12_B: Graph I - Single Source Shortest Path I": source (Python3, 0.12sec)