一.题意
给出 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;
} 
京公网安备 11010502036488号