用dp[j][k]表示j结点的连通块 大小为k的方案数
然后从叶子结点一路递推回来,分类讨论。
如果不切掉连着的边,两个连通块合并,方案数就是直接相乘
dp[u][j+k]=图片说明 dp[u][j]*dp[to][k]
如果切掉连着的边,方案数就是独立的
那么就是加上孩子的dp和,dp[u][j]=dp[u][j] * 图片说明 dp[v][k]

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=998244353;
ll n,k;
ll dp[2020][2020];//第一维度表示谁的连通块 第二维度表示连通块大小 值存方案数
ll _size[2020];
struct node
{
    int v,next;
}e[4040];
int cnt=0,head[2020];
void add(int u,int v)
{
    e[++cnt].v=v;
    e[cnt].next=head[u];
    head[u]=cnt;
}
void dfs(int u,int pre)
{
    dp[u][1]=_size[u]=1;
    for(int i=head[u];i;i=e[i].next)
    {
        int to=e[i].v;
        if(to==pre) continue;
        dfs(to,u);
        ll sum=0;
        for(int j=1;j<=min(_size[to],k);j++)
        {
            sum+=dp[to][j];
            sum%=mod;
        }
        for(int j=min(_size[u],k);j>=1;j--)
        {
            for(int p=min(_size[to],k);p>=1;p--)
            {
                if(j+p>k) continue;
                dp[u][j+p]=(dp[u][j+p]+dp[u][j]*dp[to][p])%mod;
            }
            dp[u][j]*=sum;
            dp[u][j]%=mod;
        }
        _size[u]+=_size[to];
    }
}
int main()
{
    scanf("%lld%lld",&n,&k);
    for(int i=1;i<n;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    dfs(1,1);
    ll ans=0;
    for(int i=1;i<=k;i++)
    {
        ans=(ans+dp[1][i])%mod;
    }
    printf("%lld\n",ans);
}