这是一道经典的树形dp,方法是分主子树进行dp。
坑点:主树的dp值会实时修改,所以不能用dp[ x ][ i ],只能用 temp1[ i ] - temp1[ i-1 ]
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef int lint;
const lint maxn= 5005;
const lint maxm = 10005;
const lint mod = 1e9 + 7;
lint n,m,k;
lint ver[maxm],ne[maxm],he[maxn],tot;
void add( lint x,lint y ){
ver[++tot] = y;
ne[tot] = he[x];
he[x] = tot;
}
lint ad( lint x,lint y ){
return ((LL)x+y)%mod;
}
lint mul( lint x,lint y ){
return lint(1LL*x*y%mod);
}
lint dp[maxn][maxn], key[maxn];;
void dfs( lint x,lint f ){
if( key[x] ) dp[x][0] = 1;
for( lint cure = he[x];cure;cure = ne[cure] ){
lint y = ver[cure];
if( y == f ) continue;
dfs( y,x );
static lint temp1[maxn];
temp1[0] = dp[x][0];
for( lint i = 1;i <= k;i++ ){
temp1[i] = ad( dp[x][i],temp1[i-1] );
}
static lint temp2[maxn];
temp2[0] = dp[y][0];
for( lint i = 1;i <= k;i++ ){
temp2[i] = ad( dp[y][i],temp2[i-1] );
}
for( lint i = 1;i <= k;i++ ){
lint t = min( k-i,i );
dp[x][i] = ad( dp[x][i], mul(dp[y][i-1] , temp1[t]+1) );
}
for( lint i = 1;i < k;i++ ){
lint t = min( k-i,i-1 );
if( t >= 1 )
dp[x][i] = ad( dp[x][i],mul( (temp1[i]-temp1[i-1]+mod),temp2[t-1] ) );
}
}
return;
}
int main(){
tot = 1;
scanf("%d%d%d",&n,&m,&k);
for( lint x,y,i = 1;i <= n-1;i++ ){
scanf("%d%d",&x,&y);
add( x,y );add( y,x);
}
for( lint x,i = 1;i <= m;i++ ){
scanf("%d",&x);
key[x] =1;
}
dfs(1,0);
lint ans= 0;
for( lint i = 0;i <= k;i++ ){
ans = ad( ans,dp[1][i] );
}
printf("%d\n",ans);
return 0;
}