题意:给你一棵树,树上有一些重要的点,让你选一个只包含重要的点的点集,满足点集里最远的两个点不超过k,问有多少种选法
想了好久,题解说得太简略了。。。
dp[i][j]表示在i这颗子树中距离i点最远点距离为j的方案数。
考虑如何从子树转移,显然 我们遍历到一颗新子树时,要用之前的所有方案乘以这颗子树的方案来更新。
即dp[u][max(i,j+1) ]+=dp[u][i]*dp[to][j]
暴力更新的复杂度是k^2的。需要用前缀和维护一下,
最后如果这个点可选,那么有选这个点和不选这个点两种情况,要乘2,然后加上只有这个点的情况。
最后计算总和的时候,如果这个点不是根,只加上长度为k的情况,因为其他情况还有可能去更新,会在他的祖宗里计算到,如果不是加上所有方案。
#include <bits/stdc++.h>
using namespace std;
#define N 5010
#define ll long long
#define mod 1000000007
#define go(i,a,b) for(int i=(a);i<=(b);i++)
#define dep(i,a,b) for(int i=(a);i>=(b);i--)
#define add(a,b) ((a+=(b))%=mod)
ll dp[N][N],sum[N][N],f[N],ans;
vector<int>path[N];
int is[N];
int n,m,k,x,y;
void cal(int u,int to){
go(i,1,k-1)f[i]=dp[u][i]*sum[to][min(i,k-i)-1]%mod;