結果
| 問題 |
No.3309 Aging Railway
|
| コンテスト | |
| ユーザー |
norioc
|
| 提出日時 | 2025-11-05 10:31:32 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 785 ms / 3,000 ms |
| コード長 | 2,917 bytes |
| コンパイル時間 | 2,785 ms |
| コンパイル使用メモリ | 81,956 KB |
| 実行使用メモリ | 80,804 KB |
| 最終ジャッジ日時 | 2025-11-05 10:31:49 |
| 合計ジャッジ時間 | 14,496 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 20 |
ソースコード
from collections import defaultdict
from itertools import accumulate
class LcaEdgeMinWeight:
def __init__(self, n: int, adj: dict, root=0):
"""
n: 頂点数
adj: { 頂点: [(隣接頂点, 重み), ...] }
root: 根
"""
sz = n.bit_length()
parents = [[-1] * n for _ in range(sz)]
dists = [-1] * n
min_weights = [[INF] * n for _ in range(sz)]
def dfs():
s = [(root, -1, 0, 0)]
while s:
v, par, depth, weight = s.pop()
parents[0][v] = par
dists[v] = depth
min_weights[0][v] = weight
for to, w in adj[v]:
if to == par: continue
s.append((to, v, depth+1, w))
dfs()
for k in range(sz-1):
for v in range(n):
if parents[k][v] < 0: continue
parents[k+1][v] = parents[k][parents[k][v]]
min_weights[k+1][v] = min(min_weights[k][v],
min_weights[k][parents[k][v]])
self.parents = parents
self.dists = dists
self.min_weights = min_weights
def find_min(self, u: int, v: int) -> int:
"""頂点間 (u, v) の辺の最小重みを求める"""
if self.dists[u] < self.dists[v]:
u, v = v, u
min_w = INF
sz = len(self.parents)
# LCA までの距離を同じにする
for k in range(sz):
if (self.dists[u] - self.dists[v]) >> k & 1:
min_w = min(min_w, self.min_weights[k][u])
u = self.parents[k][u]
if u == v: return min_w
for k in range(sz-1, -1, -1):
if self.parents[k][u] != self.parents[k][v]:
min_w = min(min_w,
self.min_weights[k][u],
self.min_weights[k][v])
u = self.parents[k][u]
v = self.parents[k][v]
return min(min_w,
self.min_weights[0][u],
self.min_weights[0][v])
def distance(self, u: int, v: int) -> int:
"""二頂点 u, v の距離"""
return self.dists[u] + self.dists[v] - 2 * self.dists[self.find(u, v)]
def is_on_path(self, u: int, v: int, a: int) -> bool:
"""二頂点 u, v 上に頂点 a があるか"""
return self.distance(u, a) + self.distance(a, v) == self.distance(u, v)
INF = 1 << 60
N, M = map(int, input().split())
adj = defaultdict(list)
for i in range(N-1):
u, v = map(lambda x: int(x)-1, input().split())
adj[u].append((v, i))
adj[v].append((u, i))
lca = LcaEdgeMinWeight(N, adj)
imos = [0] * N
for _ in range(M):
s, t = map(lambda x: int(x)-1, input().split())
w = lca.find_min(s, t)
imos[0] += 1
imos[w+1] -= 1
ans = list(accumulate(imos))
print(*ans[1:], sep='\n')
norioc