D - もこもこクラウドホッピング / Fluffy Cloud Hopping 解説 by admin
gpt-5.3-codexOverview
This is a shortest path problem where the state includes the “current fluffiness level.”
Instead of only vertices, we treat (cloud, current fluffiness) as a single state, rebuild the graph accordingly, and find the shortest time using Dijkstra’s algorithm.
Analysis
The difficulty of this problem lies in the fact that the movement cost depends on the “current fluffiness level you have.”
In other words, even if you are at the same cloud \(u\), if your current fluffiness \(f\) is different, the next movement cost will change.
First, a common mistake is to only maintain
dist[u] = shortest time to cloud u
and run a standard shortest path algorithm, which results in WA.
This is because even if you arrive at cloud \(u\) “a little later,” if your fluffiness at that time is smaller, subsequent movements become cheaper, and you may ultimately reach the goal faster.
The key insight is as follows:
- Define the state as \((u, f)\) (at cloud \(u\) with current fluffiness \(f\))
- Solve the shortest path in this state space
There are two types of transitions:
Adoption transition (change in place)
Upon arriving at cloud \(u\), you can change your fluffiness to \(F_u\).
This is a transition with cost \(0\): $\( (u, f) \to (u, F_u) \)$Movement transition (traversing an edge)
Traversing edge \((u,v,t)\) with current fluffiness \(f\) gives: $\( (u, f) \to (v, f),\quad \text{cost}=t \times f \)\( (In the implementation, \)f\( is 0-indexed, so the actual cost is \)t \times (f+1)$)
This results in a “shortest path with non-negative weights,” so Dijkstra’s algorithm can be applied directly.
Since the constraint \(K \le 5\) is small, the number of states \(N \times K\) is perfectly feasible.
Algorithm
- Convert fluffiness \(F_i\) to 0-indexed (\(1..K \to 0..K-1\)).
- Initialize
dist[u][f]as “shortest time to state \((u,f)\).” - The initial state is being at cloud 1 with fluffiness \(F_1\), so
dist[0][F[0]] = 0. - Run Dijkstra with a priority queue:
- From the extracted state \((u,f)\):
- Adoption transition: \((u,f) \to (u,F_u)\) (cost 0)
- For each adjacent edge \((u,v,t)\), movement transition: \((u,f)\to(v,f)\) (cost \(t \times (f+1)\))
- Push if an improvement is found
- From the extracted state \((u,f)\):
- The answer is
min(dist[N-1][f])over all \(f\). Output-1if unreachable.
Complexity
- Number of states: \(N \times K\)
- Transitions from each state: 1 adoption + number of adjacent edges
Overall, roughly \(O((NK + MK)\log(NK))\)
Therefore:
- Time complexity: \(O((N K + M K)\log(NK))\)
- Space complexity: \(O(NK + MK)\) (for dist and the equivalent state graph. The adjacency list itself in the implementation is \(O(N+M)\))
Implementation Notes
Using 0-indexed fluffiness simplifies array management (multiply movement cost by
f+1).As a standard Dijkstra technique, use
if d != dist[u][f]: continueto discard stale queue entries.Edge weights can be up to \(10^9 \times 5\), and path lengths can also become very large, so handle them safely with Python’s int (e.g., set
INF = 10**30or some sufficiently large value).Source Code
import sys
import heapq
def main():
input = sys.stdin.readline
N, M, K = map(int, input().split())
F = list(map(int, input().split()))
F = [x - 1 for x in F] # 0-indexed fluffiness
g = [[] for _ in range(N)]
for _ in range(M):
u, v, t = map(int, input().split())
u -= 1
v -= 1
g[u].append((v, t))
g[v].append((u, t))
INF = 10**30
# dist[node][f] = min time to be at node with current fluffiness f (0..K-1)
dist = [[INF] * K for _ in range(N)]
start_f = F[0]
dist[0][start_f] = 0
pq = [(0, 0, start_f)] # (cost, node, fluff)
while pq:
d, u, f = heapq.heappop(pq)
if d != dist[u][f]:
continue
# Option: adopt this cloud's fluffiness
fu = F[u]
if d < dist[u][fu]:
dist[u][fu] = d
heapq.heappush(pq, (d, u, fu))
# Move along edges with current fluffiness f
mult = f + 1
for v, t in g[u]:
nd = d + t * mult
if nd < dist[v][f]:
dist[v][f] = nd
heapq.heappush(pq, (nd, v, f))
ans = min(dist[N - 1])
print(ans if ans < INF else -1)
if __name__ == "__main__":
main()
This editorial was generated by gpt-5.3-codex.