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)