CF2028E 题解
注:定义“上”为根的方向,“下”为叶子的方向。
第一思路是 DP。
设 \(f_u\) 为从 \(u\) 出发可以逃脱的概率。
-
如果 Alice 走:她一定要往上走,往下走概率不会变高。
-
如果 Queen 走:其实她和 Alice 是对称的。她一定要往下走,往上走概率不会变高。
那她具体去哪个儿子?她应该去最浅的儿子(深度最小的),因为这样 Alice 更可能输。
综上,我们可以知道:
\[f_u = \dfrac{1}{2} (f_v + f_p)
\]
其中 \(p\) 是 \(u\) 的父亲,\(v\) 是 \(u\) 最浅的儿子。
我们惊喜的发现这没法转移,所以要变换一下式子。令 \(f_u = k_u f_p + b_u\),则:
\[\begin{aligned}
f_u
&= \dfrac{1}{2} f_p + \dfrac{1}{2} f_v \\
&= \dfrac{1}{2} f_p + \dfrac{1}{2} (k_v f_u + b_v) \\
&= \dfrac{1}{2} f_p + \dfrac{1}{2} k_v f_u + \dfrac{1}{2} b_v \\
\end{aligned}
\]
移项得:
\[\begin{aligned}
\left( k_u - \dfrac{1}{2} \right) f_p + b_u
&= \dfrac{1}{2} k_v f_u + \dfrac{1}{2} b_v \\
&= \dfrac{1}{2} k_v (k_u f_p + b_u) + \dfrac{1}{2} b_v \\
&= \dfrac{1}{2} k_v k_u f_p + \left( \dfrac{1}{2} k_v b_u + \dfrac{1}{2} b_v \right)
\end{aligned}
\]
比较系数得:
\[\begin{cases}
k_u = \dfrac{1}{2 - k_v} \\
b_u = \dfrac{b_v}{2 - k_v}
\end{cases}
\]
发现叶子的 \(k_u = b_u = 0\),所以 \(b_u\) 恒为 \(0\),那么 \(f_u = k_u f_p\)。
那么 DFS 求 \(k_u\) 后再 DFS 求 \(f_u\) 即可。
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
constexpr int MOD = 998244353;
inline int add_mod(int x, int y) { return (x + y + MOD) % MOD; }
inline int mul_mod(int x, int y) { return i64(x) * y % MOD; }
int inv_mod(int x)
{
int y = MOD - 2, res = 1;
for (; y > 0; y >>= 1, x = mul_mod(x, x)) {
if (y & 1)
res = mul_mod(res, x);
}
return res;
}
inline int div_mod(int x, int y) { return x == 1 ? inv_mod(y) : mul_mod(x, inv_mod(y)); }
struct Solution {
int n;
vector<int> depth, to, fa, k, f; // f[u] = k[u] * f[p]
vector<vector<int>> tree;
void solve1(int u)
{
for (int v : tree[u]) {
if (v != fa[u])
solve1(v);
}
int v = to[u];
if (v != -1)
k[u] = div_mod(1, add_mod(2, -k[v]));
}
void solve2(int u)
{
for (int v : tree[u]) {
if (v == fa[u])
continue;
f[v] = mul_mod(k[v], f[u]);
solve2(v);
}
}
void prep1(int u)
{
depth[u] = depth[fa[u]] + 1;
for (int v : tree[u]) {
if (v == fa[u])
continue;
fa[v] = u;
prep1(v);
}
}
void prep2()
{
queue<pair<int, int>> nodes;
for (int i = 2; i <= n; ++i) {
if (tree[i].size() == 1)
nodes.emplace(i, -1);
}
while (!nodes.empty()) {
auto [curr, from] = nodes.front();
nodes.pop();
if (to[curr] == 0)
to[curr] = from;
else
continue;
nodes.emplace(fa[curr], curr);
}
}
void main()
{
cin >> n;
k.resize(n + 1);
f.resize(n + 1);
fa.resize(n + 1);
to.resize(n + 1);
tree.resize(n + 1);
depth.resize(n + 1);
for (int i = 1; i < n; ++i) {
int u, v;
cin >> u >> v;
tree[u].push_back(v);
tree[v].push_back(u);
}
prep1(1);
prep2();
solve1(1);
f[1] = 1;
solve2(1);
for (int i = 1; i <= n; ++i)
cout << f[i] << ' ';
cout << '\n';
}
};
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
int t;
cin >> t;
while (t-- > 0)
Solution().main();
return 0;
}

浙公网安备 33010602011771号