CodeForces 735E(树形DP)
Posted Psong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces 735E(树形DP)相关的知识,希望对你有一定的参考价值。
CodeForces 735E Ostap and Tree
题意:给一棵树,需要给树上的一些节点上色,要求任意节点在距离为k的范围以内至少有一个被染色的点,求方案数。
思路:之前看别人代码,感觉好短,题解也好简略,感觉不是很明朗,现在终于感觉自己看懂一点了,来留一发。
用 dp[x][i] 记录离节点 x 最近的一个被染色的点距 x 的距离为 i ,对于其子树 dp[y][j] ,如果 i+j<=2*k,则此时 min(i,j)<=k,即在此时是成立的,因此把值存入最近的染色点f[min(i,j)];否则min(i,j)>k无法满足,将无法满足的点同样存入f[max(i,j)]中。每处理完一次子树则用 f 数组 对 dp[x] 数组进行赋值。处理子树过程中,第一次实质上时dp[u][i+1] = dp[v][i],后续的操作相当于已记录的子树 和 未记录的子树相互之间的关系,相互独立,因而满足两个基本的组合原理。最终结果为∑dp[1][i] (i<=k)。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #define mod 1000000007 using namespace std; vector<int> g[105]; int dp[105][55]; int f[55]; int n,k; void dfs(int u,int fa){ dp[u][0]=1; dp[u][k+1]=1; for(int i=0;i<g[u].size();i++){ int v=g[u][i]; if(v==fa) continue; dfs(v,u); memset(f,0,sizeof(f)); //对第一颗子树操作相当于 赋值 dp[u][i+1] = dp[v][i]; //后续的操作相当于已记录的子树 和 未记录的子树相互之间的关系,其分别的两个黑点距离为 j + p + 1; //并且改关系满足乘法原理,最终的结果记录时,如果 j + p <= 2 * k 则能够满足,则取最近的黑点,否则取最远的黑点并赋值。 for(int j=0;j<=2*k;j++) for(int p=0;p<=2*k;p++){ if(j+p<=2*k){ //min(p+1,j)<=k f[min(p+1,j)]+=(1LL*dp[u][j]*dp[v][p])%mod; f[min(p+1,j)]%=mod; } else{ //max(p+1,j)>k f[max(p+1,j)]+=(1LL*dp[u][j]*dp[v][p])%mod; f[max(p+1,j)]%=mod; } } for(int j=0;j<=2*k;j++) dp[u][j]=f[j]; } } int main(){ cin>>n>>k; for(int i=1;i<n;i++){ int x,y; cin>>x>>y; g[x].push_back(y); g[y].push_back(x); } dfs(1,1); int ans=0; for(int i=0;i<=k;i++){ ans=(ans+dp[1][i])%mod; } cout<<ans<<endl; return 0; }
以上是关于CodeForces 735E(树形DP)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 743D:Chloe and pleasant prizes(树形DP)
Codeforces 919D Substring (拓扑排序+树形dp)
CodeForces 219D Choosing Capital for Treeland (树形DP)