結果
問題 | No.2949 Product on Tree |
ユーザー | shimonohnishi |
提出日時 | 2024-11-04 10:32:15 |
言語 | PyPy3 (7.3.15) |
結果 |
TLE
|
実行時間 | - |
コード長 | 3,824 bytes |
コンパイル時間 | 217 ms |
コンパイル使用メモリ | 82,260 KB |
実行使用メモリ | 286,080 KB |
最終ジャッジ日時 | 2024-11-04 10:32:41 |
合計ジャッジ時間 | 24,274 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 37 ms
59,840 KB |
testcase_01 | AC | 37 ms
52,524 KB |
testcase_02 | AC | 37 ms
53,764 KB |
testcase_03 | TLE | - |
testcase_04 | TLE | - |
testcase_05 | TLE | - |
testcase_06 | TLE | - |
testcase_07 | TLE | - |
testcase_08 | TLE | - |
testcase_09 | TLE | - |
testcase_10 | TLE | - |
testcase_11 | TLE | - |
testcase_12 | -- | - |
testcase_13 | -- | - |
testcase_14 | -- | - |
testcase_15 | -- | - |
testcase_16 | -- | - |
testcase_17 | -- | - |
testcase_18 | -- | - |
testcase_19 | -- | - |
testcase_20 | -- | - |
testcase_21 | -- | - |
testcase_22 | -- | - |
testcase_23 | -- | - |
testcase_24 | -- | - |
testcase_25 | -- | - |
testcase_26 | -- | - |
testcase_27 | -- | - |
testcase_28 | -- | - |
testcase_29 | -- | - |
testcase_30 | -- | - |
testcase_31 | -- | - |
testcase_32 | -- | - |
testcase_33 | -- | - |
testcase_34 | -- | - |
testcase_35 | -- | - |
testcase_36 | -- | - |
testcase_37 | -- | - |
testcase_38 | -- | - |
testcase_39 | -- | - |
testcase_40 | -- | - |
testcase_41 | -- | - |
testcase_42 | -- | - |
testcase_43 | -- | - |
testcase_44 | -- | - |
testcase_45 | -- | - |
testcase_46 | -- | - |
testcase_47 | -- | - |
testcase_48 | -- | - |
ソースコード
import pypyjit import sys pypyjit.set_param('max_unroll_recursion=-1') sys.setrecursionlimit(2000000) class Rerooting: """ Rerooting クラスは、木の再根付き問題を解くためのクラスです。 木の各頂点を根とする部分木の情報を効率的に計算します。 based on: https://algo-logic.info/tree-dp Attributes: G: List[List[Edge]]: 隣接リスト。 dp: List[List[DP]]: dp[v][i]: 頂点vから出るi番目の有向辺に対応する部分木のDP。 ans: List[DP]: ans[v]: 頂点vを根とする木の答え。 Methods: add_edge(a, b): 頂点aと頂点bの間に辺を追加します。 build(): 木の再根付きDPを構築します。 dfs(v, p): 深さ優先探索を用いて部分木のDPを計算します。 bfs(v, dp_p, p): 幅優先探索を用いて部分木のDPを計算します。 Parameters: N: int: 頂点数。 class DP: DP の型。 identity: DP の単位元。 class Edge: 辺の型。 merge(d1, d2): 2つのDPをマージします。 add_root(d): 部分木のDPに根を追加します。 """ # region 問題ごとに変更する部分 class DP: # DP の型 def __init__(self, dp_): self.dp = dp_ identity = DP(0) # 単位元(末端の値は add_root(identity) になるので注意) class Edge: def __init__(self, to): self.to = to def merge(self, d1: DP, d2: DP) -> DP: return self.DP((d1.dp + d2.dp) % MOD) def add_root(self, d: DP, v: int) -> DP: return self.DP((d.dp + 1) * C[v] % MOD) # endregion # region slv def __init__(self, N: int): self.G = [[] for _ in range(N)] self.dp = [[] for _ in range(N)] self.ans = [self.identity] * N def add_edge(self, a: int, b: int): self.G[a].append(self.Edge(b)) def build(self): self.dfs(0) # 普通に木DP self.bfs(0, self.identity) # 残りの部分木に対応するDPを計算 def dfs(self, v: int, p: int = -1) -> DP: # 頂点v, 親p dp_cum = self.identity deg = len(self.G[v]) self.dp[v] = [self.identity] * deg for i in range(deg): u = self.G[v][i].to if u == p: continue self.dp[v][i] = self.dfs(u, v) dp_cum = self.merge(dp_cum, self.dp[v][i]) return self.add_root(dp_cum, v) def bfs(self, v: int, dp_p: DP, p: int = -1): # bfs だが、実装が楽なので中身は dfs になっている deg = len(self.G[v]) for i in range(deg): # 前のbfsで計算した有向辺に対応する部分木のDPを保存 if self.G[v][i].to == p: self.dp[v][i] = dp_p dp_l = [self.identity] * (deg + 1) # 累積merge dp_r = [self.identity] * (deg + 1) # 累積merge for i in range(deg): dp_l[i + 1] = self.merge(dp_l[i], self.dp[v][i]) for i in range(deg - 1, -1, -1): dp_r[i] = self.merge(dp_r[i + 1], self.dp[v][i]) self.ans[v] = self.add_root(dp_l[deg], v) # 頂点 v の答え for i in range(deg): # 一つ隣の頂点に対しても同様に計算 u = self.G[v][i].to if u == p: continue self.bfs(u, self.add_root(self.merge(dp_l[i], dp_r[i + 1]), v), v) # endregion N = int(input()) C = list(map(int, input().split())) MOD = 998244353 r = Rerooting(N) for _ in range(N - 1): u, v = map(int, input().split()) u -= 1 v -= 1 r.add_edge(u, v) r.add_edge(v, u) r.build() A = r.ans ans = 0 for a in A: ans += a.dp ans %= MOD ans -= sum(C) ans *= pow(2, MOD - 2, MOD) ans %= MOD print(ans)