题意:给一棵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. Leetcode867.Transpose Matrix转置矩阵

    给定一个矩阵 A, 返回 A 的转置矩阵. 矩阵的转置是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引. 示例 1: 输入:[[1,2,3],[4,5,6],[7,8,9]] 输出:[[1,4,7] ...

  2. Ubuntu中NS2安装详细教程

    前言: NS2是指 Network Simulator version 2,NS(Network Simulator) 是一种针对网络技术的源代码公开的.免费的软件模拟平台,研究人员使用它可以很容易的 ...

  3. 如何建一个Liferay 7的theme

    首先附上原文链接Creating theme and Deploying in liferay 7 by using Eclipse 1.第一步:建一个Liferay module 项目,选择them ...

  4. element-ui el-time-picker

    获取时分秒时间 <el-time-picker is-range v-model="time" value-format="HH:mm:ss" range ...

  5. SPSS详细操作:生存资料的Cox回归分析

    SPSS详细操作:生存资料的Cox回归分析 一.问题与数据 某研究者拟观察某新药的抗肿瘤效果,将70名肺癌患者随机分为两组,分别采用该新药和常规药物进行治疗,观察两组肺癌患者的生存情况,共随访2年.研 ...

  6. spring boot + mybatis 访问 neo4j

    之前有通过rest的风格去访问,但是每次需要访问时候将statement一并加入header中去数据库执行,方式简单.且思路清晰,但是不便于形成模板调用,固采用mybaits来集成. 1.关键pom. ...

  7. 利用阿里大于实现发送短信(JAVA版)

    本文是我自己的亲身实践得来,喜欢的朋 友别忘了点个赞哦! 最近整理了一下利用阿里大于短信平台来实现发送短信功能. 闲话不多说,直接开始吧. 首先,要明白利用大于发送短信这件事是由两部分组成: 一.在阿 ...

  8. Directx11教程(6) 画一个简单的三角形(2)

    原文:Directx11教程(6) 画一个简单的三角形(2)      在上篇教程中,我们实现了在D3D11中画一个简单的三角形,但是,当我们改变窗口大小时候,三角形形状却随着窗口高宽比例改变而改变, ...

  9. oracle触发器——ddl触发器

    什么是ddl(data definition language),说白了就是我们经常用的create.alter和drop这些数据定义语句. n  创建ddl触发器 请编写一个触发器,可以记录某个用户 ...

  10. 从url输入网址后发生什么

    从url输入网址后发生什么