一.题意

给出 n 个节点,以及最大连通块数目 k ,
可以删掉一些边,求连通块数目小于等于 k 的方案数。

二.题解





三.代码:

#include<bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define ll long long
#define fi first
#define se second
#define inf 0x3f3f3f3f
#define io std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;

const int manx=1e5+5;
const int N=2e3+5;
const int mod=1e9+7;
const int mo=998244353;

vector<ll>g[N];
ll dp[N][N],sz[N];
ll n,ans,k;

void dfs(ll u, ll pre){
    dp[u][1]=1; sz[u]=1;
    for(auto v: g[u]){
        if(v==pre) continue;
        dfs(v,u);
        ll m=min(k,sz[v]),up=min(k,sz[u]);
        ll sum=0;
        for(int i=1;i<=m;i++) sum+=dp[v][i],sum%=mo;
        for(int i=up;i;i--){
            for(int j=m;j;j--)
                if(i+j<=k)
                    dp[u][i+j]+=dp[u][i]*dp[v][j]%mo,dp[u][i+j]%=mo;
            dp[u][i]*=sum,dp[u][i]%=mo;
        }
        sz[u]+=sz[v];
    }
}

int main(){
    io; cin>>n>>k;
    for(int i=1;i<n;i++){
        ll u,v; cin>>u>>v;
        g[u].pb(v); g[v].pb(u);
    }
    dfs(1,1);
    for(int i=1;i<=k;i++)
        ans+=dp[1][i],ans%=mo;
    cout<<ans<<endl;
    return 0;
}