Official

B - 山岳地帯の雨水シミュレーション / Rainwater Simulation in Mountainous Terrain Editorial by admin

DeepSeek V3

Overview

This is a problem where we simulate water flowing between points in a mountainous region based on elevation differences, and determine the final water volume at each point after dams have been placed.

Key Observations

The crucial observation for this problem is the property that water “only flows from higher elevation points to lower elevation points.” Because of this, by processing points in order from highest to lowest elevation, we can guarantee that when processing a given point, all water inflow from higher points has already been accounted for. By fixing the processing order to descending elevation, we enable an efficient simulation.

As a naive approach, if we process all points without sorting by elevation, water flow could appear to cycle, leading to incorrect results. Additionally, if we check all adjacent points when flowing water from each point, the computational complexity becomes \(O(NM)\), which cannot be processed within the time limit under the given constraints.

Algorithm

  1. Preprocessing:

    • For each point, create a list of “downstream adjacent points” (adjacent points with strictly lower elevation) to which water can directly flow
    • Calculate the “in-degree” (number of paths through which water flows into a point) for each point (though in the actual algorithm, in-degree is not used)
  2. Determining Processing Order:

    • Sort all points in descending order of elevation. Since water does not flow between points at the same elevation, the ordering among such points does not affect the result
  3. Water Volume Simulation:

    • Process each point in the sorted order
    • If the point has a dam: Do nothing and retain the water volume
    • If there is no dam and downstream adjacent points exist: Divide the current water volume by the number of downstream adjacent points and distribute it equally among them. Reset the point’s own water volume to 0
    • If there is no dam and no downstream adjacent points exist: Retain the water volume

With this approach, by processing from higher points first, we guarantee that when processing each point, the inflow from all higher points has already been computed.

Complexity

  • Time complexity: \(O(N \log N + M)\)
    • \(O(N \log N)\) for sorting
    • \(O(M)\) for graph construction and computing downstream adjacent points
    • \(O(N + M)\) for the water volume simulation
  • Space complexity: \(O(N + M)\)
    • For storing the graph and various arrays

Implementation Notes

  • Use iterators for efficient input reading

  • Manage dam locations with a set for fast lookup

  • Be mindful of floating-point precision issues (no problem as long as results are within the tolerance specified in the problem statement)

  • Create an adjacency list that only stores downstream adjacent points to streamline processing

  • Use a lambda function during elevation-based sorting to retain point indices

    Source Code

import sys
from collections import deque

def main():
    data = sys.stdin.read().split()
    if not data:
        return
    
    it = iter(data)
    N = int(next(it)); M = int(next(it)); K = int(next(it))
    H = [0] * (N+1)
    for i in range(1, N+1):
        H[i] = int(next(it))
    W_initial = [0] * (N+1)
    for i in range(1, N+1):
        W_initial[i] = float(next(it))
    
    graph = [[] for _ in range(N+1)]
    for _ in range(M):
        u = int(next(it)); v = int(next(it))
        graph[u].append(v)
        graph[v].append(u)
    
    dam_set = set()
    if K > 0:
        for _ in range(K):
            s = int(next(it))
            dam_set.add(s)
    
    indegree = [0] * (N+1)
    adj_low = [[] for _ in range(N+1)]
    for u in range(1, N+1):
        for v in graph[u]:
            if H[u] > H[v]:
                adj_low[u].append(v)
                indegree[v] += 1
    
    order = []
    for i in range(1, N+1):
        order.append(i)
    order.sort(key=lambda x: H[x], reverse=True)
    
    water = W_initial[:]
    for u in order:
        if u in dam_set:
            continue
        d = len(adj_low[u])
        if d == 0:
            continue
        flow = water[u] / d
        for v in adj_low[u]:
            water[v] += flow
        water[u] = 0.0
    
    result = []
    for i in range(1, N+1):
        result.append(str(water[i]))
    print(" ".join(result))

if __name__ == "__main__":
    main()

This editorial was generated by deepseekv3.

posted:
last update: