結果
| 問題 |
No.898 tri-βutree
|
| コンテスト | |
| ユーザー |
brthyyjp
|
| 提出日時 | 2021-03-15 03:41:29 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 717 ms / 4,000 ms |
| コード長 | 4,175 bytes |
| コンパイル時間 | 238 ms |
| コンパイル使用メモリ | 82,176 KB |
| 実行使用メモリ | 120,692 KB |
| 最終ジャッジ日時 | 2024-11-08 23:53:57 |
| 合計ジャッジ時間 | 13,128 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 21 |
ソースコード
class HLD:
def __init__(self, g):
self.g = g
self.n = len(g)
self.parent = [-1]*self.n
self.size = [1]*self.n
self.head = [0]*self.n
self.preorder = [0]*self.n
self.k = 0
self.depth = [0]*self.n
for v in range(self.n):
if self.parent[v] == -1:
self.dfs_pre(v)
self.dfs_hld(v)
def dfs_pre(self, v):
g = self.g
stack = [v]
order = [v]
while stack:
v = stack.pop()
for u in g[v]:
if self.parent[v] == u:
continue
self.parent[u] = v
self.depth[u] = self.depth[v]+1
stack.append(u)
order.append(u)
# 隣接リストの左端: heavyな頂点への辺
# 隣接リストの右端: 親への辺
while order:
v = order.pop()
child_v = g[v]
if len(child_v) and child_v[0] == self.parent[v]:
child_v[0], child_v[-1] = child_v[-1], child_v[0]
for i, u in enumerate(child_v):
if u == self.parent[v]:
continue
self.size[v] += self.size[u]
if self.size[u] > self.size[child_v[0]]:
child_v[i], child_v[0] = child_v[0], child_v[i]
def dfs_hld(self, v):
stack = [v]
while stack:
v = stack.pop()
self.preorder[v] = self.k
self.k += 1
top = self.g[v][0]
# 隣接リストを逆順に見ていく(親 > lightな頂点への辺 > heavyな頂点 (top))
# 連結成分が連続するようにならべる
for u in reversed(self.g[v]):
if u == self.parent[v]:
continue
if u == top:
self.head[u] = self.head[v]
else:
self.head[u] = u
stack.append(u)
def for_each(self, u, v):
# [u, v]上の頂点集合の区間を列挙
while True:
if self.preorder[u] > self.preorder[v]:
u, v = v, u
l = max(self.preorder[self.head[v]], self.preorder[u])
r = self.preorder[v]
yield l, r # [l, r]
if self.head[u] != self.head[v]:
v = self.parent[self.head[v]]
else:
return
def for_each_edge(self, u, v):
# [u, v]上の辺集合の区間列挙
# 辺の情報は子の頂点に
while True:
if self.preorder[u] > self.preorder[v]:
u, v = v, u
if self.head[u] != self.head[v]:
yield self.preorder[self.head[v]], self.preorder[v]
v = self.parent[self.head[v]]
else:
if u != v:
yield self.preorder[u]+1, self.preorder[v]
break
def subtree(self, v):
# 頂点vの部分木の頂点集合の区間 [l, r)
l = self.preorder[v]
r = self.preorder[v]+self.size[v]
return l, r
def lca(self, u, v):
# 頂点u, vのLCA
while True:
if self.preorder[u] > self.preorder[v]:
u, v = v, u
if self.head[u] == self.head[v]:
return u
v = self.parent[self.head[v]]
import sys
import io, os
input = io.BytesIO(os.read(0,os.fstat(0).st_size)).readline
n = int(input())
E = []
g = [[] for i in range(n)]
edge = [[] for i in range(n)]
for i in range(n-1):
u, v, w = map(int, input().split())
g[u].append(v)
g[v].append(u)
edge[u].append((w, v))
edge[v].append((w, u))
hld = HLD(g)
dist = [-1]*n
s = []
s.append(0)
dist[0] = 0
while s:
v = s.pop()
for w, u in edge[v]:
if dist[u] == -1:
dist[u] = dist[v]+w
s.append(u)
def getDist(u, v):
l = hld.lca(u, v)
res = dist[u]+dist[v]-2*dist[l]
return res
q = int(input())
for i in range(q):
x, y, z = map(int, input().split())
ans = (getDist(x, y)+getDist(y, z)+getDist(z, x))//2
print(ans)
brthyyjp