蓝魔法师

题解:
树形dp
对于每棵子树,有两种可能
1.不删除这条边,两个点相连
2.删除这条边,两个点各自独立

定义dp[i][j] 表示 i 结点所在的连通块中节点数为 j 的方案数是多少

/*Keep on going Never give up*/
//#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <cstring>
#include <cmath>
#include <math.h>
#include <string>
#include<string.h>
#include <list>
#include <set>
#include <unordered_map>
#include <queue>
#include <stack>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#include <cctype>
#include<iomanip>
#define int long long
#define endl '\n'
using namespace std;
const int maxn = 2010;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const ll mod= 998244353;
using namespace std;
int n, kk;
vector<int> v[maxn];
ll dp[maxn][maxn];
ll isize[maxn], num[maxn];


inline void add(int x,int y){
    v[x].push_back(y);
    v[y].push_back(x);
}

void dfs(ll x, ll fa){
    dp[x][1]=1;
    isize[x]=1;
    for(ll i = 0; i < v[x].size(); i++){
        ll to = v[x][i];
        if (to == fa) continue;
        dfs(to, x);

        for(ll j=1; j <= isize[x]; j++){
            for(ll k = 0; k <= isize[to]; k++){
                if (j+k > kk) break;
                num[j+k] += dp[x][j]*dp[to][k];
                num[j+k] %= mod;
            }
        }
        isize[x] += isize[to];
        for(ll j = 1; j <= isize[x]; j++) dp[x][j] = num[j], num[j] = 0;
    }
    for(ll i = 1; i <= kk; i++){
        dp[x][0] = (dp[x][0]+dp[x][i])%mod;
    }
}

signed main() {
    cin >> n >> kk;
    ll x, y;

    for(ll i = 1; i < n; i++){
        cin>>x>>y;
        add(x,y);
    }
    dfs(1, 0);
    ll ans = 0;
    for(ll i = 1; i <= kk; i++) ans = (ans+dp[1][i])%mod;
    cout<<ans<<endl;
    return 0;
}
题解 文章被收录于专栏

主要写一些题目的题解

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务