题意:给一棵n个结点的无根树染色,求使每个结点距离为k的范围内至少有一个被染色的结点的总染色方法数目

分析:首先我们定义: 对于结点v, 如果存在一个黑色结点u距离v不超过k,则结点v被“控制”

   首先将无根树转换成以1为根的有根树,设dp[v][i]为对于以v为根的子树,距离v最近的黑色结点深度为i时, 该子树中结点全部被控制或者可能在其他子树的影响下被全部控制的染色方法数。

   下面来解释一下, 我们知道,当两个黑色结点距离不超过2*k+1时,其间的所有节点都被控制。那么当 i <= k 时,子树中的结点可以被全部控制, 当 k + 1 <= i <= 2*k+1 时, 子树中的节点不可能自动全被控制,但是可能在该子树根结点染色以及其他子树影响下被全部控制。

   如何计算v的dp值呢,假如v只有一个儿子u, 那么 dp[v][i] = dp[u][i-1]; 如果v有多个儿子,那么首先按上述方法合并v和第一个子树,然后将子树v与其他子树合并。

   那么如何合并两棵子树v, u呢?

   首先考虑v的根结点为白色的状态,可以枚举(i,j)的所有情况,其中 i 是第一棵子树最近黑结点的深度(i>0),j 是第二棵子树最近黑结点的深度,如果i+j <= 2*k,则更新dp[v][min(i, j+1)], 这个状态是节点全部被控制的状态。如果i+j > 2*k, 则此状态子树中节点无法自发地全部被控制,但是可以在其他子树的影响下被全部控制。

   if  i+j <= 2*k , update dp[v][min(i, j+1)]

   else update dp[v][max(i,  j+1)]

   计算完根结点为白色的情况之后,考虑根结点为黑色,那么最近距离v节点不超过2*k+1的情况数目之和就是所求,

                即 dp[v][0] = ∑ dp[v][i] ( i from 1 to 2*k+1 )

   比较难以理解的地方是一个子树全为白色的情况如何进行更新,其实可以这样想,对于每个叶子节点u,假想距离u节点k+1的深度有一个黑色结点,那么对于子树u,dp[u][0] = 1,这是子树完全被控制的情况, dp[u][k+1] = 1, 这是该叶子节点可能在其他子树影响下被控制的情况。这样对于所有节点都可以以上述方式更新。

ps:此题难点在于状态的设计以及状态的转移方法,需要反复琢磨。

附上代码:

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream> using namespace std;
typedef long long LL; #define M 1000000007
#define rep(i, x, n) for(int i = x; i <= (n); i++)
const int maxn = ;
const int maxk = + ; LL dp[maxn][*maxk];
LL temp[*maxk]; vector<int> G[maxn];
int n, k;
void dfs(int v, int f) {
int len = G[v].size();
if(G[v].size() == && f != ) { //处理除 1 这个根结点之外的叶子
dp[v][] = dp[v][k+] = ;
return ;
}
int flag = ;
rep(i, , len-) {
int u = G[v][i];
if(u == f) continue;
dfs(u, v);
if(!flag) {
rep(i, , *k) dp[v][i+] = dp[u][i];
flag = ;
}
else {
rep(i, , *k+) temp[i] = dp[v][i], dp[v][i] = ;
rep(i, , *k) rep(j, , *k+)
if(i+j <= *k) dp[v][min(j, i+)] = (dp[v][min(j, i+)] + temp[j]*dp[u][i]) % M;
else dp[v][max(j, i+)] = (dp[v][max(j, i+)] + temp[j]*dp[u][i]) % M;
}
}
//计算子树根结点为黑色的情况
rep(i, , *k+) dp[v][] = (dp[v][] + dp[v][i]) % M;
}
int main(){
scanf("%d%d", &n, &k);
rep(i, , n) G[i].clear();
memset(dp, , sizeof dp);
for(int i = ;i < n; i++){
int a, b;
scanf("%d%d",&a, &b);
G[a].push_back(b);
G[b].push_back(a);
}
dfs(, );
LL ans = ;
for(int i = ;i <= k; i++)
ans = (ans + dp[][i])%M;
if(!ans) ans = ;
cout << ans << endl;
return ;
}

codeforce 382 div2 E —— 树状dp的更多相关文章

  1. 树状DP (poj 2342)

    题目:Anniversary party 题意:给出N各节点的快乐指数,以及父子关系,求最大快乐指数和(没人职员愿意跟直接上司一起玩): 思路:从底向上的树状DP: 第一种情况:第i个员工不参与,F[ ...

  2. poj3659树状DP

    Cell Phone Network Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6273   Accepted: 225 ...

  3. hdu 1561 The more, The Better_树状dp

    题目链接 题意:给你一棵树,各个节点都有价值(除根节点),从根节点出发,选择m个节点,问最多的价值是多小. 思路:很明显是树状dp,遍历树时背包最优价值,dp[i][k]=max{dp[i][r]+d ...

  4. poj 2342 Anniversary party_经典树状dp

    题意:Ural大学有n个职员,1~N编号,他们有从属关系,就是说他们关系就像一棵树,父节点就是子节点的直接上司,每个职员有一个快乐指数,现在要开会,职员和职员的直接上司不能同时开会,问怎才能使开会的快 ...

  5. 树状DP HDU1520 Anniversary party

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1520 题意:职员之间有上下级关系,每个职员有自己的happy值,越高在派对上就越能炒热气氛.但是必须是 ...

  6. [Codeforces743D][luogu CF743D]Chloe and pleasant prizes[树状DP入门][毒瘤数据]

    这个题的数据真的很毒瘤,身为一个交了8遍的蒟蒻的呐喊(嘤嘤嘤) 个人认为作为一个树状DP的入门题十分合适,同时建议做完这个题之后再去做一下这个题 选课 同时在这里挂一个选取节点型树形DP的状态转移方程 ...

  7. HDU 4714 Tree2cycle(树状DP)(2013 ACM/ICPC Asia Regional Online ―― Warmup)

    Description A tree with N nodes and N-1 edges is given. To connect or disconnect one edge, we need 1 ...

  8. poj2486--Apple Tree(树状dp)

    Apple Tree Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7789   Accepted: 2606 Descri ...

  9. 洛谷P2015 二叉苹果树(树状dp)

    题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来 ...

随机推荐

  1. Apple Watch和Apple Pay将助苹果成为首家市值万亿美元公司

    苹果公司周二盘中市值首次突破7000亿美元,成为标普中首家市值超过7000亿美元的公司,市值是第二名Exxon的1.7倍.有分析师预测苹果在明年的市值将会逼近8000亿美元,不过如果参考著名激进投资人 ...

  2. pandas使用手册

    工欲善其事必先利其器,在使用Python做数据挖掘和数据分析时,一大必不可少的利器就是Pandas库了.pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的,其纳入了大量库 ...

  3. kubernetes1.5新特性跟踪

    Kubernetes发布历史回顾 Kubernetes 1.0 - 2015年7月发布 Kubernetes 1.1 - 2015年11月发布 Kubernetes 1.2 - 2016年3月发布 K ...

  4. spring-cloud-zuul跨域问题解决

    问题发现 正常情况下,跨域是这样的: 1. 微服务配置跨域+zuul不配置=有跨域问题 2. 微服务配置+zuul配置=有跨域问题 3. 微服务不配置+zuul不配置=有跨域问题 4. 微服务不配置+ ...

  5. hdu3879 最大权闭合图

    若a,b 2点能够相连,那么可以得到ci的价值,也就是说a,b是得到c的前提条件,对于每一个点,又有耗费. 对于本题,先求出最多能够得到的利益有多少,最小割=未被 选的用户的收益之和 + 被选择的站点 ...

  6. iOS 9 学习系列:UIStack View

    http://www.cocoachina.com/ios/20150921/13492.html 在 iOS9 中,Apple 引入了 UIStackView,他让你的应用可以通过简单的方式,纵向或 ...

  7. 安装软件时候出现"无效驱动器D"

    安装软件的时候,出现以下问题. 如图:  无效驱动器 原因是因为之前安装过这样的软件在H盘,后期更改没了H,所以出现了错误. 解决方案: 打开注册表,搜索软件的关键字如  vmware 删除错误路径即 ...

  8. 开通了第一个博客,mark一下!

    今日上网查询了不同的博客,包括csdn.掘金等,最终决定选择博客园.打算待前端学完后,自己建立一个博客,这段时间内先用博客园记录学习过程.经常总结.更新,相信坚持学习一定可以找到好工作!

  9. 【JZOJ4832】【NOIP2016提高A组集训第3场10.31】高维宇宙

    题目描述 数据范围 解法 由于大于4的素数只有可能由奇数和偶数的和得出. 所以根据数的奇偶性可以分出两类数奇数和偶数. 奇数之间不会相互匹配,偶数之间也不会相互匹配. 那么原问题转化为二分图最大匹配. ...

  10. beanstalkd 启动跟停止

    启动命令: nohup /usr/bin/beanstalkd -l xxx.xxx.xxx.xxx -p 11300 & >> /dev/null 2>&1 正常启 ...