首页 > 代码库 > CodeForces 735E(树形DP)
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)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。