codeforce 382 div2 E —— 树状dp
题意:给一棵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的更多相关文章
- 树状DP (poj 2342)
题目:Anniversary party 题意:给出N各节点的快乐指数,以及父子关系,求最大快乐指数和(没人职员愿意跟直接上司一起玩): 思路:从底向上的树状DP: 第一种情况:第i个员工不参与,F[ ...
- poj3659树状DP
Cell Phone Network Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6273 Accepted: 225 ...
- hdu 1561 The more, The Better_树状dp
题目链接 题意:给你一棵树,各个节点都有价值(除根节点),从根节点出发,选择m个节点,问最多的价值是多小. 思路:很明显是树状dp,遍历树时背包最优价值,dp[i][k]=max{dp[i][r]+d ...
- poj 2342 Anniversary party_经典树状dp
题意:Ural大学有n个职员,1~N编号,他们有从属关系,就是说他们关系就像一棵树,父节点就是子节点的直接上司,每个职员有一个快乐指数,现在要开会,职员和职员的直接上司不能同时开会,问怎才能使开会的快 ...
- 树状DP HDU1520 Anniversary party
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1520 题意:职员之间有上下级关系,每个职员有自己的happy值,越高在派对上就越能炒热气氛.但是必须是 ...
- [Codeforces743D][luogu CF743D]Chloe and pleasant prizes[树状DP入门][毒瘤数据]
这个题的数据真的很毒瘤,身为一个交了8遍的蒟蒻的呐喊(嘤嘤嘤) 个人认为作为一个树状DP的入门题十分合适,同时建议做完这个题之后再去做一下这个题 选课 同时在这里挂一个选取节点型树形DP的状态转移方程 ...
- 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 ...
- poj2486--Apple Tree(树状dp)
Apple Tree Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7789 Accepted: 2606 Descri ...
- 洛谷P2015 二叉苹果树(树状dp)
题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来 ...
随机推荐
- 【水滴石穿】RNNewsGo
项目地址为:https://github.com/ImVeryGood/RNNewsGo 我们先来看一下页面 分析了一下项目,项目也是有用到redux-saga的 然后模块比较清晰 接下来我们分析代码 ...
- 三.BP神经网络
BP神经网络是包含多个隐含层的网络,具备处理线性不可分问题的能力.以往主要是没有适合多层神经网络的学习算法,,所以神经网络的研究一直处于低迷期. 20世纪80年代中期,Rumelhart,McClel ...
- umount报错解决device is busy
umount –a 报错device is busy如图 df -h 执行 umount -l /dev/sdk1 fuser -m -v /cache10 再查看卸载了
- database homework3
查询所有大于60分的学生的姓名和学号 (DISTINCT: 去重) mysql> select student.sname,student.sid,score.number from stude ...
- 利用阿里大于实现发送短信(JAVA版)
本文是我自己的亲身实践得来,喜欢的朋 友别忘了点个赞哦! 最近整理了一下利用阿里大于短信平台来实现发送短信功能. 闲话不多说,直接开始吧. 首先,要明白利用大于发送短信这件事是由两部分组成: 一.在阿 ...
- More Effective C++: 04效率
16:牢记80-20准则 80-20准则说的是大约20%的代码使用了80%的程序资源:大约20%的代码耗用了大约80%的运行时间:大约20%的代码使用了80%的内存:大约20%的代码执行80%的磁盘访 ...
- thinkphp 公用函数
thinkphp 的项目中指定了common/function.php的函数是公用函数. 不但php页面可以使用,模板文件也可以使用:
- LeetCode97 Interleaving String
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. (Hard) For example,Giv ...
- 3DMAX安装失败怎样卸载重新安装3DMAX,解决3DMAX安装失败的方法总结
技术帖:3DMAX没有按照正确方式卸载,导致3DMAX安装失败.楼主也查过网上关于如何解决3DMAX安装失败的一些文章,是说删除几个3DMAX文件和3DMAX软件注册表就可以解决3DMAX安装失败的问 ...
- [考试维护]之IIS发布 标签: iis 2015-06-07 22:11 627人阅读 评论(18) 收藏
考试维护也进行了一段时间了,总结一下这段时间学习到的东西,今天写一下在服务器上如何发布IIS,一开始,我们准备了两台服务器,一台Win Server2003的服务器(IIS版本6.0),另一台是Win ...