树上删掉一些边后使图连通的方案数
链接:https://www.nowcoder.com/acm/contest/215/C
来源:牛客网
题目描述
“你,你认错人了。我真的,真的不是食人魔。”--蓝魔法师
输入描述:
第一行两个整数n,k, 表示点数和限制
2 <= n <= 2000, 1 <= k <= 2000
接下来n-1行,每行包括两个整数u,v,表示u,v两点之间有一条无向边
保证初始图联通且合法
输出描述:
共一行,一个整数表示方案数对998244353取模的结果
示例1
输出
复制7
思路分析 :
定义dp[i][j] 表示 i 结点所在的连通块中节点数为 j 的方案数是多少
代码示例 :
#define ll long long ll n, kk; vector<ll>ve[2005]; ll dp[2005][2005]; ll size[2005], num[2005]; void dfs(ll x, ll fa){ dp[x][1] = 1; size[x] = 1; for(ll i = 0; i < ve[x].size(); i++){ ll to = ve[x][i]; if (to == fa) continue; dfs(to, x); for(ll j = 1; j <= size[x]; j++){ for(ll k = 0; k <= size[to]; k++){ if (j+k > kk) break; num[j+k] += dp[x][j]*dp[to][k]; num[j+k] %= mod; } } size[x] += size[to]; for(ll j = 1; j <= size[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; } } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); cin >> n >> kk; ll x, y; for(ll i = 1; i < n; i++){ scanf("%lld%lld", &x, &y); ve[x].push_back(y); ve[y].push_back(x); } dfs(1, 0); ll ans = 0; for(ll i = 1; i <= kk; i++) ans = (ans+dp[1][i])%mod; printf("%lld\n", ans); return 0; }
东北日出西边雨 道是无情却有情