HDU6540 Neko and tree(樹形dp)
阿新 • • 發佈:2020-10-29
本題難想的是狀態設計,因為要做到不重不漏,所以我們設計狀態為f[i][j]表示以i為根,子樹中到i點最大距離為j的方案數。
那麼在更新的時候,只要根據新的子樹和之前所有的子樹的關係即可更新,因為很多j都可以成為答案,如果再列舉一維就會超過複雜度
因此使用字首和優化,來降維到二維dp
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=4e5+10; const int mod=1e9+7; int h[N],ne[N],e[N],idx; ll f[5050][5050]; ll sum[View Code5050][5050]; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } int n,m,k; int in[N]; ll tmp[5050]; void init(){ int i,j; for(i=0;i<=n;i++){ h[i]=-1; in[i]=0; for(j=0;j<=n;j++){ f[i][j]=0; sum[i][j]=0; } } } void cal(int u,intv) { for(int i=1;i<=k;i++) tmp[i]=f[u][i]*sum[v][min(i-1,k-i-1)]%mod; for(int i=1;i<=k;i++) tmp[i]=(tmp[i]+sum[u][min(i,k-i)]*f[v][i-1])%mod; for(int i=1;i<=k/2;i++) tmp[i]=(tmp[i]+mod-f[u][i]*f[v][i-1]%mod)%mod; for(int i=1;i<=k;i++) { f[u][i]=(f[u][i]+tmp[i]+f[v][i-1])%mod; sum[u][i]=(sum[u][i-1]+f[u][i])%mod; } } void dfs(int u,int fa){ int i; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa) continue; dfs(j,u); cal(u,j); } if(in[u]){ for(i=1;i<=k;i++) f[u][i]=f[u][i]*2%mod; f[u][0]=1; } sum[u][0]=f[u][0]; for(i=1;i<=k;i++){ sum[u][i]=(sum[u][i-1]+f[u][i])%mod; } } int main(){ ios::sync_with_stdio(false); cin>>n>>m>>k; init(); int i; for(i=1;i<n;i++){ int a,b; cin>>a>>b; add(a,b); add(b,a); } for(i=1;i<=m;i++){ int x; cin>>x; in[x]=1; } dfs(1,-1); cout<<sum[1][k]<<endl; }