banner
NEWS LETTER

Johnson全源最短路径 - Python模板

Scroll down

简介

模板使用defaultdict实现, 不必要时可以更换list减少内存开销.
有结果时返回一个字典, 有负环返回None.
查询方式print(johnson(e, nodes)[start][end])

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
from random import randint
from collections import defaultdict, deque
import heapq


def dijkstra(e, s):
vis = set()
queue = [(0, s)]
dis = defaultdict(lambda: float("+inf"))
dis[s] = 0
while queue:
_, u = heapq.heappop(queue)
if u in vis:
continue
vis.add(u)
for v, w in e[u]:
if dis[v] > dis[u] + w:
dis[v] = dis[u] + w
heapq.heappush(queue, (dis[v], v))
return dis


def spfa(e, s):
dis = defaultdict(lambda: float("+inf"))
dis[s] = 0
queue = deque([s])
in_queue = defaultdict(bool)
in_queue[s] = True
count = defaultdict(int)
count[s] = 1

while queue:
u = queue.popleft()
in_queue[u] = False

for v, w in e[u]:
if dis[v] > dis[u] + w:
dis[v] = dis[u] + w
if not in_queue[v]:
queue.append(v)
in_queue[v] = True
count[v] += 1
if count[v] > len(e):
return None
return dis


def johnson(e, nodes):
virtual_node = hex(randint(1 << (4 * 4), 1 << (5 * 4)))
e[virtual_node] = [(node, 0) for node in nodes]

h = spfa(e, virtual_node)
if h is None:
return None

new_edges = defaultdict(list)
for u in e:
for v, w in e[u]:
new_edges[u].append((v, w + h[u] - h[v]))

result = defaultdict(lambda: defaultdict(lambda: float("+inf")))
for u in nodes:
dist = dijkstra(new_edges, u)
result[u].update({v: dist[v] - h[u] + h[v] for v in dist if v != virtual_node})

return result

使用案例

# P7551 [COCI 2020/2021 #6] Alias

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
e = defaultdict(list)
points = set()
n, m = map(int, input().split())
for i in range(m):
a, b, t = input().split()
e[a].append((b, int(t)))
points.add(a)
points.add(b)


dis = johnson(e, points)

for i in range(int(input())):
a, b = input().split()
if dis[a][b] < float("+inf"):
print(dis[a][b])
else:
print("Roger")
其他文章
目录导航 置顶
  1. 1. 简介
  2. 2. 代码
  3. 3. 使用案例
    1. 3.1.