Editorial for Nuclear Waste
Approach
Solve the problem in three Bellman-Ford-style passes.
Pass 1. Compute how far each location is from the nearest nuclear waste site. Treat the given directed edges as undirected and run multi-source Bellman-Ford from every waste location. Call this value waste[v].
Pass 2. The safety of a route is the minimum waste[v] over vertices v on the route. Maximize safety from 1 to n with another Bellman-Ford: the state at each node is the best bottleneck so far, and relaxing a→b yields min(safety[a],waste[b]).
Pass 3. Among routes that achieve that maximum safety S, maximize total food. Restrict to nodes with waste[v]≥S (any visit below S would drop safety). Run Bellman-Ford maximizing food on that subgraph.
After n−1 food relaxations, the value at node n is optimal among simple routes. Then run n
further relaxations and check whether the food at n alone increases. The first of those n
iterations updates nodes on a positive-food cycle (if any); up to n−1 more may be needed for
that improvement to reach n. If n's food changes, output -1.
With n≤200 and m≤500, the time complexity O(nm) is acceptable.
Solution (Python)
import sys
INF = 10**30
NEG_INF = -INF
def main() -> None:
data = list(map(int, sys.stdin.buffer.read().split()))
n, m, w_count = data[0], data[1], data[2]
wastes = [x - 1 for x in data[3 : 3 + w_count]]
idx = 3 + w_count
edges: list[tuple[int, int, int, int]] = []
rev_edges: list[tuple[int, int, int]] = []
for _ in range(m):
fro = data[idx] - 1
to = data[idx + 1] - 1
weight = data[idx + 2]
food = data[idx + 3]
idx += 4
edges.append((fro, to, weight, food))
rev_edges.append((to, fro, weight))
# Pass 1: undirected distance from the nearest waste site.
waste_dist = [INF] * n
for site in wastes:
waste_dist[site] = 0
for _ in range(n - 1):
updated = False
for fro, to, weight, _ in edges:
if waste_dist[fro] == INF:
continue
cand = waste_dist[fro] + weight
if cand < waste_dist[to]:
waste_dist[to] = cand
updated = True
for fro, to, weight in rev_edges:
if waste_dist[fro] == INF:
continue
cand = waste_dist[fro] + weight
if cand < waste_dist[to]:
waste_dist[to] = cand
updated = True
if not updated:
break
# Pass 2: maximum path safety (bottleneck) from 1 to n.
safety = [NEG_INF] * n
safety[0] = waste_dist[0]
for _ in range(n - 1):
updated = False
for fro, to, _, _ in edges:
if safety[fro] == NEG_INF:
continue
cand = min(safety[fro], waste_dist[to])
if cand > safety[to]:
safety[to] = cand
updated = True
if not updated:
break
target_safety = safety[n - 1]
# Pass 3: maximum food among routes that keep safety == target_safety.
# Only visit nodes whose waste distance is at least target_safety.
food = [NEG_INF] * n
if waste_dist[0] >= target_safety:
food[0] = 0
for _ in range(n - 1):
updated = False
for fro, to, _, edge_food in edges:
if food[fro] == NEG_INF or waste_dist[to] < target_safety:
continue
cand = food[fro] + edge_food
if cand > food[to]:
food[to] = cand
updated = True
if not updated:
break
finite_food = food[n - 1]
# One more full n iterations: a positive-food cycle updates on the first of
# these, and up to n-1 further iterations may be needed for that improvement
# to reach node n.
for _ in range(n):
for fro, to, _, edge_food in edges:
if food[fro] == NEG_INF or waste_dist[to] < target_safety:
continue
cand = food[fro] + edge_food
if cand > food[to]:
food[to] = cand
ans_food = food[n - 1]
if ans_food != finite_food:
ans_food = -1
print(target_safety, ans_food)
if __name__ == "__main__":
main()
Comments0
No comments yet
Be the first to comment.
New comment
Log in to join the discussion.