D - 山岳縦走 / Mountain Traverse Editorial by admin
Claude 4.6 Opus (Thinking)Overview
Starting from mountain hut \(1\), we want to find the maximum number of mountain huts we can visit while following one-way trails such that the altitude is strictly monotonically increasing. This can be reduced to the longest path problem on a DAG (Directed Acyclic Graph).
Analysis
Key Insight: The Graph is a DAG
Among the trails \(U_j \to V_j\), only those satisfying \(P_{U_j} < P_{V_j}\) (the destination’s altitude is higher than the source’s) can actually be used in a “good traverse.” Edges that cannot be used (\(P_{U_j} \geq P_{V_j}\)) can be removed in advance.
All remaining edges point “from lower altitude to higher altitude.” Since all mountain huts have distinct altitudes, the graph composed of only these edges contains no cycles. This is because following a cycle would require the altitude to keep increasing and then return to its starting value, which is impossible.
Therefore, this graph is a DAG (Directed Acyclic Graph).
Problem with a Naive Approach
An exhaustive search (enumerating all paths via DFS) could result in an exponential number of paths, causing TLE under the constraints where \(N, M\) can be up to \(2 \times 10^5\).
Solution
The longest path on a DAG can be efficiently computed using topological sort + dynamic programming (DP).
Algorithm
Graph Construction: For each edge \((U_j, V_j)\), add it to the adjacency list only if \(P_{U_j} < P_{V_j}\). This yields a DAG.
Topological Sort: Compute the topological order using Kahn’s algorithm (BFS that repeatedly extracts vertices with in-degree 0).
Compute the Longest Path with DP:
- Define \(dp[v]\) as “the maximum number of mountain huts on a path from mountain hut \(1\) to mountain hut \(v\).”
- Initial values: \(dp[1] = 1\) (starting point), and \(dp[v] = 0\) for all others (unreached).
- Following the topological order, for each vertex \(u\), if \(dp[u] > 0\) (reachable from mountain hut \(1\)), update each adjacent vertex \(v\) as \(dp[v] = \max(dp[v],\ dp[u] + 1)\).
Answer: Output \(\max(dp[v])\) (the maximum value among all vertices).
Concrete Example
If there are 3 mountain huts with altitudes \(P = [-, 10, 30, 20]\) (1-indexed), and edges \(1 \to 2\), \(1 \to 3\), \(3 \to 2\): - Valid edges (altitude increasing): \(1 \to 2\) (\(10 < 30\)), \(1 \to 3\) (\(10 < 20\)), \(3 \to 2\) (\(20 < 30\)) - Topological order: \(1, 3, 2\) - DP: \(dp[1]=1 \to dp[3]=2 \to dp[2]=3\) - Answer: \(3\) (path: \(1 \to 3 \to 2\))
Complexity
- Time complexity: \(O(N + M)\) — Graph construction, topological sort, and DP are all linear in the number of vertices and edges.
- Space complexity: \(O(N + M)\) — For storing the adjacency list, in-degree array, and DP array.
Implementation Notes
Edge Filtering: By excluding edges that do not satisfy \(P[u] < P[v]\) during graph construction, the DAG property is guaranteed. Forgetting this may introduce cycles, causing the topological sort to not work correctly.
Skipping Unreachable Vertices: During DP transitions, skip vertices where \(dp[u] = 0\). This prevents updates from vertices that are not reachable from mountain hut \(1\).
Fast I/O: In Python, reading all input at once with
sys.stdin.buffer.read()helps avoid TLE even with large inputs.Source Code
import sys
from collections import deque
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
P = [0] * (N + 1)
for i in range(1, N + 1):
P[i] = int(input_data[idx]); idx += 1
# We need to find the longest path starting from node 1,
# following directed edges, with strictly increasing P values.
# Build adjacency list only for edges where P[u] < P[v] (valid edges)
adj = [[] for _ in range(N + 1)]
in_degree = [0] * (N + 1)
for j in range(M):
u = int(input_data[idx]); idx += 1
v = int(input_data[idx]); idx += 1
if P[u] < P[v]:
adj[u].append(v)
in_degree[v] += 1
# This is a DAG (since edges only go from lower P to higher P, and P values are distinct).
# We want the longest path from node 1 in this DAG.
# Topological sort using Kahn's algorithm
topo = []
queue = deque()
in_deg = in_degree[:]
for i in range(1, N + 1):
if in_deg[i] == 0:
queue.append(i)
while queue:
u = queue.popleft()
topo.append(u)
for v in adj[u]:
in_deg[v] -= 1
if in_deg[v] == 0:
queue.append(v)
# DP: longest path from node 1
# dp[v] = maximum number of nodes in a path from 1 to v
dp = [0] * (N + 1)
dp[1] = 1 # start at node 1
for u in topo:
if dp[u] == 0:
continue # not reachable from node 1
for v in adj[u]:
if dp[u] + 1 > dp[v]:
dp[v] = dp[u] + 1
print(max(dp))
if __name__ == '__main__':
main()
This editorial was generated by claude4.6opus-thinking.