公式

D - 最短避難経路 / Shortest Evacuation Route 解説 by admin 印刷ページ

Claude 4.6 Opus (Thinking)

Overview

This is a problem of finding the shortest path from point \(1\) to point \(N\) on a graph where passing through flooded points incurs additional time penalties. It can be solved by applying the basic Dijkstra’s algorithm while accounting for the penalties at flooded points.

Analysis

Understanding the Essence of the Problem

This problem is a shortest path problem on a weighted graph, but it differs from the usual formulation in that there are not only edge costs but also vertex traversal costs.

Specifically: - When traversing edge \((u, v)\), the edge weight \(w\) is incurred - Additionally, if the destination vertex \(v\) is flooded, an extra time penalty of \(T\) is incurred - If the starting point \(1\) is flooded, the time penalty of \(T\) is also incurred at the beginning

Converting Vertex Costs to Edge Costs

Problems with vertex costs can be reduced to standard edge-cost-only shortest path problems by adding the cost of entering a vertex to the cost of all edges leading to that vertex.

For example, if vertex \(v\) is flooded, we add \(T\) to the cost of all edges directed toward \(v\). For the starting point \(1\), we set the initial cost to \(T\) (if it is flooded).

Concrete Example

Suppose there are 3 points \(1, 2, 3\), with edges \((1, 2, 5)\) and \((2, 3, 3)\), and point \(2\) is flooded (\(T = 10\)):

  • Point \(1\) → Point \(2\): edge cost \(5\) + flooding cost \(10\) = \(15\)
  • Point \(2\) → Point \(3\): edge cost \(3\) + flooding cost \(0\) = \(3\)
  • Total: \(15 + 3 = 18\)

Algorithm

  1. Read the input and build the graph using an adjacency list
  2. Create a set of flooded points (use a set for \(O(1)\) lookup)
  3. Run Dijkstra’s algorithm as follows:
    • Initial cost: \(T\) if point \(1\) is flooded, \(0\) otherwise
    • When moving to \(v\) via edge \((u, v, w)\), the cost is \(w + (\)if point \(v\) is flooded then \(T\), else \(0)\)
    • Use a priority queue (min-heap) to update the shortest distance to each vertex
  4. Output \(dist[N]\)

This is essentially standard Dijkstra’s algorithm, with the only modification being that the flooding cost of the destination vertex is added to the edge weight.

Complexity

  • Time complexity: \(O((N + M) \log N)\)
    • This is the standard complexity of Dijkstra’s algorithm. At most one heap operation (\(O(\log N)\)) is performed per edge.
  • Space complexity: \(O(N + M)\)
    • This is the space required for the adjacency list, distance array, and the set of flooded points.

Implementation Notes

  • Use a set (set) for checking flooded points: Linear search through a list would be slow, so use a set that allows \(O(1)\) lookup.

  • Don’t forget to handle flooding at the starting point: If point \(1\) is flooded, the initial distance must be set to \(T\). Forgetting this will result in WA.

  • Input handling when \(K = 0\): When there are \(0\) flooded points, the line listing flooded points may not be given, so be careful when reading input.

  • Watch out for overflow: The edge weight \(w\) and \(T\) can be up to \(10^9\), and the total can become large for long paths. In Python, there is no integer overflow issue, but in C++ and similar languages, you need to use long long.

    Source Code

import heapq
import sys

def main():
    input_data = sys.stdin.buffer.read().split()
    idx = 0
    N = int(input_data[idx]); idx += 1
    M = int(input_data[idx]); idx += 1
    K = int(input_data[idx]); idx += 1
    T = int(input_data[idx]); idx += 1
    
    adj = [[] for _ in range(N + 1)]
    for i in range(M):
        u = int(input_data[idx]); idx += 1
        v = int(input_data[idx]); idx += 1
        w = int(input_data[idx]); idx += 1
        adj[u].append((v, w))
        adj[v].append((u, w))
    
    flooded = set()
    if K > 0:
        for j in range(K):
            g = int(input_data[idx]); idx += 1
            flooded.add(g)
    
    # Dijkstra from node 1 to node N
    # When visiting a node that is flooded, add T to the cost
    INF = float('inf')
    dist = [INF] * (N + 1)
    
    start_cost = T if 1 in flooded else 0
    dist[1] = start_cost
    
    pq = [(start_cost, 1)]
    
    while pq:
        d, u = heapq.heappop(pq)
        if d > dist[u]:
            continue
        if u == N:
            break
        for v, w in adj[u]:
            extra = T if v in flooded else 0
            nd = d + w + extra
            if nd < dist[v]:
                dist[v] = nd
                heapq.heappush(pq, (nd, v))
    
    print(dist[N])

main()

This editorial was generated by claude4.6opus-thinking.

投稿日時:
最終更新: