主要思路
- 找到所有最短的路径(使用Dijkstra)
- 对这些路径逐个遍历(使用DFS)
- 根据题意算出每条路径所需自行车和剩余自行车
- 找到最优路径并输出
使用Dijkstra找到所有的最短路径
需要在基础的Dijkstra上做些更改,把prev
向量改成一个矩阵,在更新prev
矩阵时需要做出相应的改变。
mmax = 1 << 32 - 1
C_max, N, S_p, M = map(int, input().split())
bikes = list(map(int, input().split()))
bikes.insert(0,0)
perfect = C_max / 2
paths = [[mmax for _ in range(N+1)] for _ in range(N+1)]
for i in range(M):
start, end, distance = map(int, input().split())
paths[start][end] = distance
paths[end][start] = distance
dist = paths[0].copy()
prev = [[] for _ in range(N + 1)]
for i, dd in enumerate(dist):
if dd != mmax:
prev[i] = [0]
visited = [False] * (N + 1)
visited[0] = True
for i in range(N + 1):
min_val = mmax
for ii, dd in enumerate(dist):
if (not visited[ii]) and min_val > dd:
min_val = dd
k = ii
visited[k] = True
for ii, dis in enumerate(paths[k]):
tmp = mmax if mmax == dis else dis + min_val
if (not visited[ii]):
if tmp < dist[ii]:
prev[ii] = []
dist[ii] = tmp
prev[ii].append(k)
elif tmp == dist[ii]:
prev[ii].append(k)
使用DFS遍历所有路径
因为每条路径需要独立遍历,单层DFS是不够的,需要使用双层DFS。
在遍历的同时维护最小的所需自行车和剩余自行车
stack, res, need_min, remain_min = [[S_p]], [], mmax, mmax
while len(stack) != 0:
need, remain, node = 0, 0, stack.pop()
if node[-1] == 0:
for ii in range(len(node)-2, -1, -1):
if bikes[node[ii]] > perfect:
remain += (bikes[node[ii]] - perfect)
elif bikes[node[ii]] < perfect:
gap = perfect - bikes[node[ii]]
if remain < gap:
need += (gap - remain)
remain = 0
else:
remain = remain - gap
if need < need_min or (need == need_min and remain < remain_min):
res, remain_min, need_min = node, remain, need
else:
for sub_node in prev[node[-1]]:
node.append(sub_node)
stack.append(node.copy())
node.pop()
输出结果
把上述过程得到的need_min
, remain_min
, res
格式化输出即可:
ans = []
for x in res:
ans.append(str(x))
ans.reverse()
print(f'{0 if need_min == mmax else int(need_min)} {"->".join(ans)} {0 if remain_min == mmax else int(remain_min)}')