树形Dp:[ABC036D] 塗り絵 题解

在这里插入图片描述

洛谷题解,原链接:link

思路简述

本题是一道基础树形 Dp

定义 D p i , 0 Dp_{i,0} Dpi,0 代表第 i i i 个节点涂白色的方案数;

同理 D p i , 1 Dp_{i,1} Dpi,1 代表第 i i i 个节点涂黑色的方案数。

接着是状态转移方程。

首先我们所采用的遍历树的方法是后序遍历,这很好理解;

接着根据题意可以知道 D p i , 0 Dp_{i,0} Dpi,0 D p j , 0 Dp_{j,0} Dpj,0 D p j , 1 Dp_{j,1} Dpj,1 转移而来,其中 j j j i i i 的子节点;

进一步推出 D p i , 1 Dp_{i,1} Dpi,1 仅由 D p j , 0 Dp_{j,0} Dpj,0 转移而来。

更进一步的,用乘法原理可以得到状态转移方程为:
D p i , 0 = ∏ j ∈ E d g e i D p j , 1 + D p j , 0 Dp_{i,0}=\prod_{j\in Edge_i}Dp_{j,1}+Dp_{j,0} Dpi,0=jEdgeiDpj,1+Dpj,0
D p i , 1 = ∏ j ∈ E d g e i D p j , 0 Dp_{i,1}=\prod_{j\in Edge_i}Dp_{j,0} Dpi,1=jEdgeiDpj,0

其中 E d g e i Edge_i Edgei 表示 i i i 的子节点。

思路部分结束。

代码与易错点

先放代码:

#include <bits/stdc++.h>
#define ll long long
#define Mod 1000000007
using namespace std;

ll a[100005];
ll Dp[100005][2];
ll n;
vector<ll> Edge[100005];

void dfs(ll fa, ll step) { //树形Dp
	Dp[step][1] = Dp[step][0] = 1;
	for (auto x : Edge[step]) {
		if (x == fa) continue; //切记不可删
		dfs (step, x);
		Dp[step][0] = (Dp[step][0] * (Dp[x][1] + Dp[x][0]) % Mod) % Mod; //状态转移
		Dp[step][1] = (Dp[step][1] * Dp[x][0]) % Mod;
	}
}

int main() {
	cin >> n;
	for (ll i = 1; i < n; i++) {
		ll fa, son;
		cin >> fa >> son;
		Edge[fa].push_back(son); //双向建树
		Edge[son].push_back(fa);
	}
	dfs(0, 1);
	cout << (Dp[1][1] + Dp[1][0]) % Mod; //一定要模
	return 0;
}

易错点

  1. 忘开 l o n g   l o n g long~long long long
  2. 忘取模。
  3. 输出成 (Dp[n][1] + Dp[n][0]) % Mod (本人在这里卡了好久…)。
  4. 忘记双向建树。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值