結果
| 問題 |
No.1212 Second Path
|
| コンテスト | |
| ユーザー |
lam6er
|
| 提出日時 | 2025-03-31 17:47:35 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 4,021 bytes |
| コンパイル時間 | 344 ms |
| コンパイル使用メモリ | 82,048 KB |
| 実行使用メモリ | 152,536 KB |
| 最終ジャッジ日時 | 2025-03-31 17:49:07 |
| 合計ジャッジ時間 | 10,424 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | -- * 3 |
| other | TLE * 1 -- * 44 |
ソースコード
import sys
from sys import stdin
from collections import deque
sys.setrecursionlimit(1 << 25)
input = sys.stdin.readline
def main():
import sys
n = int(sys.stdin.readline())
edges = [[] for _ in range(n + 1)] # 1-based
for _ in range(n - 1):
u, v, w = map(int, sys.stdin.readline().split())
edges[u].append((v, w))
edges[v].append((u, w))
LOG = 20
parent = [[-1] * (n + 1) for _ in range(LOG)]
depth = [0] * (n + 1)
dist = [0] * (n + 1) # distance from root to node
root = 1
stack = [(root, -1, 0, 0)]
while stack:
node, par, d, di = stack.pop()
parent[0][node] = par
depth[node] = d
dist[node] = di
for neighbor, w in edges[node]:
if neighbor != par:
stack.append((neighbor, node, d + 1, di + w))
# Build binary lifting table
for k in range(1, LOG):
for v in range(1, n + 1):
if parent[k - 1][v] != -1:
parent[k][v] = parent[k - 1][parent[k - 1][v]]
def lca(u, v):
if depth[u] < depth[v]:
u, v = v, u
# Bring u to the same depth as v
for k in range(LOG - 1, -1, -1):
if depth[u] - (1 << k) >= depth[v]:
u = parent[k][u]
if u == v:
return u
for k in range(LOG - 1, -1, -1):
if parent[k][u] != -1 and parent[k][u] != parent[k][v]:
u = parent[k][u]
v = parent[k][v]
return parent[0][u]
def get_path(u, lca_node):
path = []
while u != lca_node:
path.append(u)
u = parent[0][u]
path.append(lca_node)
return path
q = int(sys.stdin.readline())
for _ in range(q):
x, y = map(int, sys.stdin.readline().split())
if x == y:
print(-1)
continue
l = lca(x, y)
path_x = get_path(x, l)
path_y = get_path(y, l)
path = path_x + path_y[-2::-1] # Combine x to lca and y to lca (reversed)
if len(path) == 1:
print(-1)
continue
# Build edge set
edge_set = set()
for i in range(len(path) - 1):
u = path[i]
v = path[i + 1]
if u > v:
u, v = v, u
edge_set.add((u, v))
min_candidate = float('inf')
# Sort the edges for each node to optimize checking
sorted_edges = [[] for _ in range(n + 1)]
for u in range(n + 1):
sorted_edges[u] = sorted(edges[u], key=lambda x: x[1])
for u in path:
next_idx = path.index(u) + 1 if u != path[-1] else -1
prev_idx = path.index(u) - 1
neighbors_in_path = set()
if prev_idx >= 0:
prev_node = path[prev_idx]
neighbors_in_path.add(prev_node)
if next_idx < len(path) and next_idx >= 0:
next_node = path[next_idx]
neighbors_in_path.add(next_node)
# Check each adjacent edge of u
for v, w in sorted_edges[u]:
# Check if (u, v) is in edge_set
a, b = (u, v) if u < v else (v, u)
if (a, b) not in edge_set:
candidate = 2 * w
if candidate < min_candidate:
min_candidate = candidate
break # Since sorted, the first one is minimal
# Check if v is not in the neighbors_in_path
# Because sometimes, the edge is part of the path but not in the edge_set (unlikely)
# but wait, no, edge_set contains all edges in the path, so if (a, b) is in edge_set, it's part of the path
# Now, after checking all adjacent edges
if min_candidate != float('inf'):
s = dist[x] + dist[y] - 2 * dist[l]
print(s + min_candidate)
else:
print(-1)
if __name__ == "__main__":
main()
lam6er