树形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](y1)+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 修复工程

BZOJ 2133 切割(树形DP,树上背包)大概是本题全网第一篇题解 >_<BZOJ 修复工程

AcWing 311. 月之谜 数位dp

树形DP三色二叉树

树形DP三色二叉树