牛牛染颜色

传送门
题意:给出一个有根树,求满足条件的染色方案的数目,条件:任意两个染黑的点的LCA必须也为黑点。

思路:

我一看到LCA就会想到自己还不会倍增的恐惧 很显然的树形DP。既然是DP,就只用考虑初始状态和状态转移。
状态转移方程:(dp[u][1]为将u点染黑,dp[u][0]为不染)
d p [ u ] [ 0 ] = 1 + ∑ v ∈ s o n [ u ] ( d p [ v ] [ 1 ] + d p [ v ] [ 0 ] − 1 ) dp[u][0]=1+\sum_{v\in son[u]}^{}(dp[v][1]+dp[v][0]-1) dp[u][0]=1+∑v∈son[u]​(dp[v][1]+dp[v][0]−1)
d p [ u ] [ 1 ] = ∏ v ∈ s o n [ u ] ( d p [ v ] [ 1 ] + d p [ v ] [ 0 ] ) dp[u][1]=\prod_{v\in son[u]}^{}(dp[v][1]+dp[v][0]) dp[u][1]=∏v∈son[u]​(dp[v][1]+dp[v][0])
初始状态:
d p [ u ] [ 0 ] = d p [ u ] [ 1 ] = 1 dp[u][0]=dp[u][1]=1 dp[u][0]=dp[u][1]=1

对于状态转移方程的解释:

当点u不涂黑时,如果u有两个或以上子树有涂黑的点,那么就不满足“任意两个黑节点的LCA也是黑色的”。因此,只能有至多一个子树有涂黑的点。当涂黑的点存在于以v为根的子树中,其他子树必然都没涂黑,因此情况数等于以v为根的子树的总情况数: d p [ v ] [ 1 ] + d p [ v ] [ 0 ] dp[v][1]+dp[v][0] dp[v][1]+dp[v][0]。每个子树都有可能成为那个特殊的子树,因此情况累加。但是,我们要注意, d p [ v ] [ 0 ] dp[v][0] dp[v][0]包含以v为根的子树都不涂黑的情况(而此时其他树也都没有黑点:即空集),每加上这样一项,都加上了一个空集,重复了。于是每加这样一项都把空集减去(-1)。空集在最外面加回来就行了。

当点u涂黑时,点u的所有儿子都可以选择涂黑或不涂,这样都满足LCA也为黑色。那么情况数就等于每个子树的合法情况数目之间相乘的(因为相互不影响)。每棵子树的情况数目等于子树的根v涂与不涂的情况数目之和。

初始状态:涂黑算一种情况,不涂也是一种情况。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1000005;
ll head[maxn],tot=0;
ll dp[maxn][3];
struct node{int to,next;
}e[maxn*2];
void adde(int u,int v){++tot;e[tot].next=head[u];e[tot].to=v;head[u]=tot;
}
inline int read(){int f=1,x=0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
//运用dfs
void dfs(int u,int fa){dp[u][0]=dp[u][1]=1;for(int i=head[u];i;i=e[i].next){int v=e[i].to;if(v==fa) continue;dfs(v,u);dp[u][1]=(dp[u][1]*(dp[v][0]+dp[v][1]))%mod;dp[u][0]=(dp[u][0]+dp[v][0]+dp[v][1]-1)%mod;}
}
int main(){int n=read();for(int i=1;i<=n-1;i++){int u=read(),v=read();adde(u,v);adde(v,u);}dfs(1,0);printf("%lld\n",(dp[1][0]+dp[1][1])%mod);
}

[ACM]【树形DP/LCA】牛客练习赛62 牛牛染颜色相关推荐

  1. 牛客练习赛89——牛牛小数点(未解决)

    牛牛小数点 题意: 题解: 本题先说结论: 对于一个数x=2a∗5b∗px=2^a*5^b*px=2a∗5b∗p 如果p=1,也就是质因子只有2和5,则x是不循环小数,即f(x)=0 如果p!=1,则 ...

  2. 牛客练习赛34 E little w and Digital Root(数位dp)

    title: 牛客练习赛34 E little w and Digital Root(数位dp) date: 2018-12-17 22:38:37 tags: 数位dp categories:ACM ...

  3. 牛客练习赛52 | C | [烹饪] (DP,裴蜀定理,gcd)

    牛客练习赛52 C 烹饪 链接:https://ac.nowcoder.com/acm/contest/1084/C来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 327 ...

  4. 牛客练习赛81 E. 小 Q 与函数求和 1( “简单莫比乌斯反演” ,欧拉函数性质)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 牛客练习赛81 E. 小 Q 与函数求和 1( "简单莫比乌斯反演" ) Prob ...

  5. 解题报告(一)C、(牛客练习赛41 F)简单数学题(数论 + FWT)(3.5)

    繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...

  6. 牛客练习赛34 - C little w and Segment Coverage(思维、树状数组)

    title: 牛客练习赛34 - C little w and Segment Coverage(思维.树状数组) date: 2018-12-15 16:36:55 tags: [树状数组,思维] ...

  7. 踩不出足迹(牛客练习赛88 )

    踩不出足迹(牛客练习赛88 ) 题意: 长度为n的数组a,每个数是一个k位二进制 定义一下操作: 令第一次得到的结果为 a1a_1a1​.你需要从第二个数开始,每次可以选择与上一次得到的结果异或或者同 ...

  8. 2021牛客练习赛90

    2021牛客练习赛90 B.寒冬信使 C.盾与战锤 B.寒冬信使 题目链接:https://ac.nowcoder.com/acm/contest/11180/B code: #include< ...

  9. 最小生成树--牛客练习赛43-C

    牛客练习赛43-C 链接: https://ac.nowcoder.com/acm/contest/548/C 来源:牛客网 题目描述 ​ 立华奏是一个刚刚开始学习 OI 的萌新. 最近,实力强大的 ...

最新文章

  1. js控制select数据绑定下拉列表
  2. SEO -- 搜索引擎优化
  3. STM32F4 HAL库开发 -- DMA
  4. JDK synchronized的实现细节
  5. 百度地图API地理位置和坐标转换
  6. 5938. 找出数组排序后的目标下标
  7. html文件设置ftp6,vsftp的安装与配置
  8. python 项目构建工具_GitHub - shjlone/emake: 你见过的最简单的 GCC/CLANG 项目构建工具(python3版本)...
  9. java中1%4是多少,四则运算(java) 王哲文 邹庭和
  10. u盘不显示盘符但能识别怎么回事
  11. 严版快速排序Partion方法
  12. c++ vector api summary
  13. Linux下编译CMake
  14. LoadRunner教程(8)-LoadRunner 负载生成器
  15. Vmware虚拟机文件复制及改名称方法
  16. XXL-JOB任务调度
  17. 关于固态硬盘的一些总结
  18. rgb 与 #开头16进制 HEX颜色值关系转换,颜色值透明度的百分数对应十六进制表
  19. 为什么要把DAO作为接口 再用impl类来实现?
  20. 51单片机控制电动机正反转和调速

热门文章

  1. C语言结构体数组成员的赋值
  2. 我要开始写游戏啦~~~~
  3. php 手势验证码,通过微信小程序如何实现手势图案锁屏
  4. twaver html5软件价格,TWaver HTML5 (2D)----数据元素
  5. WPF C#开发中利用SQLDMO进行数据库备份还原操作中的注意点
  6. 李宏毅机器学习分类详解
  7. 弛豫压控振荡器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  8. 如何从零开始用 C++ 开发一款游戏引擎?
  9. 自定义线程池拒绝策略
  10. 背投影拼接显示墙的组成及其种类[转]