結果
問題 | No.2949 Product on Tree |
ユーザー | shimonohnishi |
提出日時 | 2024-11-04 10:29:18 |
言語 | PyPy3 (7.3.15) |
結果 |
RE
|
実行時間 | - |
コード長 | 3,712 bytes |
コンパイル時間 | 394 ms |
コンパイル使用メモリ | 82,560 KB |
実行使用メモリ | 251,508 KB |
最終ジャッジ日時 | 2024-11-04 10:30:09 |
合計ジャッジ時間 | 49,808 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 39 ms
54,000 KB |
testcase_01 | AC | 39 ms
53,212 KB |
testcase_02 | AC | 39 ms
53,032 KB |
testcase_03 | AC | 1,576 ms
212,920 KB |
testcase_04 | AC | 1,583 ms
210,804 KB |
testcase_05 | AC | 1,606 ms
214,584 KB |
testcase_06 | AC | 1,614 ms
217,268 KB |
testcase_07 | AC | 1,539 ms
214,340 KB |
testcase_08 | AC | 1,647 ms
220,252 KB |
testcase_09 | RE | - |
testcase_10 | RE | - |
testcase_11 | RE | - |
testcase_12 | RE | - |
testcase_13 | RE | - |
testcase_14 | RE | - |
testcase_15 | RE | - |
testcase_16 | RE | - |
testcase_17 | RE | - |
testcase_18 | RE | - |
testcase_19 | RE | - |
testcase_20 | RE | - |
testcase_21 | RE | - |
testcase_22 | RE | - |
testcase_23 | AC | 1,541 ms
215,472 KB |
testcase_24 | AC | 1,533 ms
215,864 KB |
testcase_25 | AC | 1,611 ms
218,156 KB |
testcase_26 | AC | 1,659 ms
218,156 KB |
testcase_27 | AC | 1,674 ms
219,688 KB |
testcase_28 | AC | 1,721 ms
223,284 KB |
testcase_29 | RE | - |
testcase_30 | RE | - |
testcase_31 | RE | - |
testcase_32 | RE | - |
testcase_33 | RE | - |
testcase_34 | RE | - |
testcase_35 | RE | - |
testcase_36 | RE | - |
testcase_37 | RE | - |
testcase_38 | RE | - |
testcase_39 | RE | - |
testcase_40 | RE | - |
testcase_41 | RE | - |
testcase_42 | RE | - |
testcase_43 | AC | 630 ms
202,200 KB |
testcase_44 | AC | 629 ms
203,668 KB |
testcase_45 | AC | 777 ms
251,508 KB |
testcase_46 | AC | 702 ms
224,148 KB |
testcase_47 | AC | 538 ms
182,532 KB |
testcase_48 | AC | 721 ms
228,804 KB |
ソースコード
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) 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)