树形DP月之暗面
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树形DP月之暗面相关的知识,希望对你有一定的参考价值。
题目链接
https://ac.nowcoder.com/acm/contest/11187/D
x中普通颜色,y中特殊颜色,要求任意两个节点如果染得都是特殊颜色要求不一样,求所有的染色方案
本题需要找好状态表示。
父节点的颜色会影响子节点的选择的颜色种类,(但是如果确定了子节点染了什么染色,无法确定父节点所染的颜色种类,所以注定是从根往子节点推)我们可以发现
- 父节点染普通颜色,子节点可以染
x
种普通颜色和y
种特殊颜色 - 父节点染特殊颜色,子节点可以染
x
中普通颜色和y - 1
种特殊颜色
便有:
- 状态表示:
状态中的根节点i
只是说了染了什么种类的颜色,只是某一种颜色(该种颜色有很多类)
f
[
i
]
[
0
]
f[i][0]
f[i][0]:i
节点染普通颜色时,子树中的染色总情况(不包含i
节点的染色情况,i
节点只是说了染了什么种类的颜色)
f
[
i
]
[
1
]
f[i][1]
f[i][1]:i
节点染特殊颜色时,子树中的染色总情况
- 状态转移:
可能有多个子树,多个子树的情况互相独立,所以要乘起来
f
[
u
]
[
1
]
=
f
[
u
]
[
1
]
∗
(
f
[
v
]
[
1
]
∗
(
y
−
1
)
+
f
[
v
]
[
0
]
∗
x
)
f[u][1] = f[u][1] * (f[v][1] * (y - 1) + f[v][0] * x )
f[u][1]=f[u][1]∗(f[v][1]∗(y−1)+f[v][0]∗x)
f
[
u
]
[
0
]
=
f
[
u
]
[
0
]
∗
(
f
[
v
]
[
1
]
∗
y
+
f
[
v
]
[
0
]
∗
x
)
f[u][0] = f[u][0] * (f[v][1] * y + f[v][0] * x)
f[u][0]=f[u][0]∗(f[v][1]∗y+f[v][0]∗x)
代码
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int mod = 998244353;
void solve()
int n, x, y;
cin >> n >> x >> y;
vector<vector<int>> g(n + 1);
for(int i = 1; i < n; i++)
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
vector<vector<ll>> f(n + 1,vector<ll>(2));
function<void(int, int)> dfs = [&](int u, int p) -> void
f[u][1] = f[u][0] = 1;
for(int i = 0; i < g[u].size(); i++)
int v = g[u][i];
if(v == p) continue;
dfs(v, u);
f[u][1] = f[u][1] * (f[v][1] * (y - 1) % mod + f[v][0] * x % mod) % mod;
f[u][0] = f[u][0] * (f[v][1] * y % mod + f[v][0] * x % mod) % mod;
;
dfs(1, -1);
cout << (f[1][0] * x % mod + f[1][1] * y % mod) % mod << "\\n";
int main()
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
// cin >> t;
t = 1;
while(t--)
solve();
return 0;
以上是关于树形DP月之暗面的主要内容,如果未能解决你的问题,请参考以下文章
[树形dp] aw3760. 最大剩余油量(树的直径+树形dp+aw周赛007_3)
BZOJ 2133 切割(树形DP,树上背包)大概是本题全网第一篇题解 >_<BZOJ 修复工程