树形DP

树形DP

知识要点

树形dp就是在“树”的数据结构上的dp ,用递推(叶子到根,根到叶子。)的方法,使得在更小规模的时候,子集容易找。难点:转移。(父亲,兄弟,子树)

常用方法

 1.换根操作

2.链上统计

例题

1. 依赖背包

先对树进行DFS,得到DFS序。

mx[i]表示i这个节点及其子树中,DFS序最大的值

dp[i][j]表示第i个点及以后的dfs序构成的泛化物品,体积大小为j的最大权值。

则dp[ i ][ j ] = max( dp[  mx[ i]+1 ][ j ],dp[ i+1 ][ j-w[ i ] ]+v[ i ] )

2. codeforces 219 D

这道题还是很简单的。首先可以很轻易的求出对于一个点的对应值(dp[u]=sum(dp[son[u]]+<son[u],u>)

而之后只要进行换根操作,每次考虑一条边就行了。

3. poj  3170

。。。裸的重心

dp[i]表示i这个子树内,节点个数

ans=min(max(n-dp[i],sum[dp[son[i]]]));

4. (无题号)给你一颗树,每个节点都有权值,有些节点也是陷阱。现在从树上一点出发,不经过重复的节点,到另一个节点终止,并且经过最大不超过C个陷阱(C<4),要求路径的权值和最大。

dp[i][j]表示从i出发,向下,经过j个陷阱的最大权值。

dp[i][j]=max(dp[son[i]][j-[i是陷阱]]+val[i])

然后换根操作或者链上统计(更简单)即可

5. Hdu 4980

对于一个边统计,向上经过的次数一定<=2(否则可以合并两条从而达到更好的效果),那么dp[i][j]

表示i这个节点的子树的边全部访问完全,并且有j条向上的队员。

粘代码:

for(int i=0;i<=2;i++)dp[u][i]=i*k;

for(int i=0;i<=2;i++)temp[i]=INF;

temp[0]=min(dp[u][1]+dp[v][1]-k+e[ss].w,dp[u][2]+dp[v][2]-2*k+2*e[ss].w);

temp[1]=min(dp[u][0]+dp[v][1]+e[ss].w,dp[u][1]+dp[v][2]-k+2*e[ss].w);

temp[1]=min(temp[1],dp[u][2]+dp[v][1]-k+e[ss].w);       temp[2]=min(dp[u][0]+dp[v][2]+2*e[ss].w,dp[u][1]+dp[v][1]+e[ss].w);

temp[2]=min(temp[2],dp[v][2]+dp[u][2]-k+2*e[ss].w);

for(int i=0;i<=2;i++)dp[u][i]=tmp[i];


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值