結果
| 問題 |
No.3283 Labyrinth and Friends
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-09-20 23:26:49 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 277 ms / 2,000 ms |
| コード長 | 2,968 bytes |
| コンパイル時間 | 598 ms |
| コンパイル使用メモリ | 82,840 KB |
| 実行使用メモリ | 80,640 KB |
| 最終ジャッジ日時 | 2025-09-25 21:03:19 |
| 合計ジャッジ時間 | 7,851 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 45 |
ソースコード
import sys
sys.setrecursionlimit(10000)
INF = 10**30
def solve():
data = sys.stdin.read().strip().split()
if not data:
return
it = iter(data)
N = int(next(it))
X = int(next(it))
if N == 1:
print(0)
return
parents = [0]*(N+1)
for i in range(2, N+1):
parents[i] = int(next(it))
c = [0]*(N+1)
s = [0]*(N+1)
for i in range(2, N+1):
c[i] = int(next(it))
s[i] = int(next(it))
# children list
children = [[] for _ in range(N+1)]
for i in range(2, N+1):
children[parents[i]].append(i)
# DFS returns dp array length X+1: dp[k] = min cost to obtain exactly k status from this node's descendants
# assuming this node itself is already unlocked. Index X means ">= X".
def dfs(v):
# start: from no children, dp[0]=0
dp = [INF] * (X+1)
dp[0] = 0
cur_max = 0 # maximum k reachable currently (<= X)
for u in children[v]:
child_dp = dfs(u) # child_dp[t_sub] = cost to get t_sub from u's descendants when u is unlocked
# build opt array for this child: opt[t] = min cost to get total t from this child-branch
# option t=0: not unlocking child => cost 0
opt = [INF] * (X+1)
opt[0] = 0
# find child's possible max t_sub (where child_dp[t_sub] < INF)
child_max_sub = 0
for t_sub in range(X+1):
if child_dp[t_sub] < INF:
child_max_sub = t_sub
# we can choose to unlock child: total status = s[u] + t_sub
for t_sub in range(child_max_sub+1):
cost_sub = child_dp[t_sub]
if cost_sub >= INF:
continue
tot = s[u] + t_sub
if tot > X:
tot = X
# cost includes unlocking child
opt[tot] = min(opt[tot], c[u] + cost_sub)
# compute child_possible_max (max j with opt[j] < INF)
child_max = 0
for j in range(X+1):
if opt[j] < INF:
child_max = j
# merge dp and opt into new_dp, bounds are cur_max and child_max
new_max = min(X, cur_max + child_max)
new_dp = [INF] * (X+1)
for i_k in range(cur_max+1):
ci = dp[i_k]
if ci >= INF:
continue
for j_k in range(child_max+1):
cj = opt[j_k]
if cj >= INF:
continue
nk = i_k + j_k
if nk > X:
nk = X
val = ci + cj
if val < new_dp[nk]:
new_dp[nk] = val
dp = new_dp
cur_max = new_max
return dp
root_dp = dfs(1)
ans = root_dp[X]
print(ans)
if __name__ == "__main__":
solve()