题意:给一棵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. 洛谷P1929 迷之阶梯

    P1929 迷之阶梯 题目描述 在经过地球防卫小队的数学家连续多日的工作后,外星人发的密码终于得以破解.它 告诉我们在地球某一处的古老遗迹中,存在有对抗这次灾难的秘密武器.防卫小队立即赶 到这处遗迹. ...

  2. JQuery--基础动画、滑动动画、淡入淡出动画、自定义动画

    /** * [JQ基础动画] * show() 显示 * hide() 隐藏 * toggle() 切换 * 默认无动画,如果要产生动画 * 在括号内,添加毫秒数,可产生动画和控制动画的快慢 * * ...

  3. less知识点总结(一)

    1.unit 删除或更换单位. 参数: dimension: 带单位或不带单位的数字. unit: (可选) 目标单位,如果省略此参数,则删除单位. See convert for changing ...

  4. 足迹地图 搜索jvectormap

    https://blog.wangjunfeng.com/foot_print/

  5. 使用 Docker/LXC 迅速启动一个桌面系统

    使用 Docker/LXC 迅速启动一个桌面系统 Docker 是 dotCloud 最近几个月刚宣布的开源引擎,旨在提供一种应用程序的自动化部署解决方案,简单的说就是,在 Linux 系统上迅速创建 ...

  6. 剑指offer 1-6

    1. 二维数组中的查找 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数.   分析 ...

  7. could not insert: [com.trs.om.bean.UserLog] The user specified as a definer ('root'@'127.0.0.1') does not exist

    2019-07-01 11:24:09,315 [http-8080-24] org.hibernate.util.JDBCExceptionReporter logExceptionsWARN: S ...

  8. linux下的远程数据库(Oracle)中文乱码问题

    适用于本地客户端(PLSQL Developer )访问远程数据库时,查询结果出现的乱码,当在远程数据库上查询结果时显示正常. 1.查询远程数据库的编码: select userenv('langua ...

  9. Excel中IP地址排序

    思路 将IP地址按"."分隔,提取"."之间的每个数,然后根据提取出的列从左至右进行主要字段及次要字段排序 公式说明 返回一个字符串在另一个字符串中出现的起始位 ...

  10. Xcode 中的Bundle versions string, short 和 Bundle version 区别

    Bundle version is the internal version number of your app. Short version string is the publically vi ...