結果

問題 No.898 tri-βutree
ユーザー brthyyjpbrthyyjp
提出日時 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
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 218 ms
120,692 KB
testcase_01 AC 39 ms
53,120 KB
testcase_02 AC 40 ms
53,376 KB
testcase_03 AC 40 ms
53,504 KB
testcase_04 AC 40 ms
53,888 KB
testcase_05 AC 41 ms
53,760 KB
testcase_06 AC 41 ms
54,016 KB
testcase_07 AC 665 ms
118,336 KB
testcase_08 AC 674 ms
118,552 KB
testcase_09 AC 658 ms
118,500 KB
testcase_10 AC 623 ms
118,744 KB
testcase_11 AC 677 ms
118,572 KB
testcase_12 AC 664 ms
118,448 KB
testcase_13 AC 676 ms
118,032 KB
testcase_14 AC 639 ms
118,640 KB
testcase_15 AC 674 ms
118,704 KB
testcase_16 AC 665 ms
118,700 KB
testcase_17 AC 661 ms
117,800 KB
testcase_18 AC 665 ms
118,708 KB
testcase_19 AC 695 ms
118,444 KB
testcase_20 AC 689 ms
118,316 KB
testcase_21 AC 717 ms
118,348 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

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)
0