Codeforces Round #382 (Div. 2) E. Ostap and Tree
2016-12-02 16:28
260 查看
题意,有一个树,可以在树上的节点上填黑色,问,保证每个节点距离问k以内都存在黑色节点的方案数。
dp[i][j]代表对于第i个节点当距离他距离为j的节点为黑色可取的方案数,因为要考虑分叉的情况,可能叙述与前面的解释不符合(我语文不好怪我喽)。
先把树转化成有根树,对于一个点v,如果它只有一个儿子u,那么dp[v][i] = dp[u][i-1];
如果不止一个儿子。那么先按上述方案处理。然后处理第二个子树的时候,它可行的方案数就是第二个子树的可行数乘以第三个子树的可行数。不过需要注意的一点是装态转移的时候左右儿子的深度会对这个节点的父亲造成一些影响。分为左右子树可以互相影响和不能互相影响的情况。可以互相影响的意思是左右子树最上面的节点的距离在2*k以内,这样要把状态转移到min(i,j) 不然转移到max(i,j)里。因为如果左右子树不会有影响,那么当其中一个子树到它的一个父亲的距离大于2*k那么对于这个父亲,这一类方案就是不可行的,但是如果左右可以互相影响,只要有一个子树到这个父亲的距离在2*k以内,那么这一类方案就是可行的,这就是区别。
dp[i][j]代表对于第i个节点当距离他距离为j的节点为黑色可取的方案数,因为要考虑分叉的情况,可能叙述与前面的解释不符合(我语文不好怪我喽)。
先把树转化成有根树,对于一个点v,如果它只有一个儿子u,那么dp[v][i] = dp[u][i-1];
如果不止一个儿子。那么先按上述方案处理。然后处理第二个子树的时候,它可行的方案数就是第二个子树的可行数乘以第三个子树的可行数。不过需要注意的一点是装态转移的时候左右儿子的深度会对这个节点的父亲造成一些影响。分为左右子树可以互相影响和不能互相影响的情况。可以互相影响的意思是左右子树最上面的节点的距离在2*k以内,这样要把状态转移到min(i,j) 不然转移到max(i,j)里。因为如果左右子树不会有影响,那么当其中一个子树到它的一个父亲的距离大于2*k那么对于这个父亲,这一类方案就是不可行的,但是如果左右可以互相影响,只要有一个子树到这个父亲的距离在2*k以内,那么这一类方案就是可行的,这就是区别。
#include<bits/stdc++.h> using namespace std; const int N = 105,K = 100; long long dp [K]; long long old[K]; int n,k; vector<int> G ; const long long MOD = 1e9+7; bool vis ; void dfs(int v,int fa){ if(G[v].size()== 1&&fa != -1){ dp[v][0] = 1; dp[v][k+1] = 1; return ; } int flag = 0; for(int i= 0;i < G[v].size();i ++){ int t = G[v][i]; if(t == fa) continue; dfs(t,v); if(flag == 0){ for(int i= 0;i <= 2*k+1;i ++){ dp[v][i+1] = dp[t][i]; } flag = 1; } else{ for(int i= 0;i <= 2*k+1;i ++){ old[i] = dp[v][i]; dp[v][i]= 0; } for(int i = 0;i <= 2*k;i ++){ for(int j= 1;j <= 2*k+1;j ++){ if(i+j<=2*k){ dp[v][min(j,i+1)] += old[j]*dp[t][i]; dp[v][min(j,i+1)] %= MOD; } else { dp[v][max(j,i+1)] += old[j]*dp[t][i]; dp[v][max(j,i+1)] %= MOD; } } } } } for(int i= 1;i <=2*k+1;i ++){ dp[v][0] += dp[v][i]; dp[v][0] %= MOD; } } int main(){ scanf("%d%d",&n,&k); for(int i= 1;i < n;i ++){ int a,b; scanf("%d%d",&a,&b); G[a].push_back(b); G[b].push_back(a); } memset(dp,0,sizeof(dp)); dfs(1,-1); long long ans = 0; for(int i= 0;i <= k;i ++){ //cout << i << ' ' << dp[1][i] << endl; ans += dp[1][i]; ans %= MOD; } if(ans == 0) ans = 1; cout << ans << endl; return 0; }
相关文章推荐
- Codeforces Round #382 (Div. 1) C. Ostap and Tree
- Codeforces Round #382 (Div. 1) C. Ostap and Tree(树形DP)
- Codeforces Round #264 (Div. 2) E. Caisa and Tree 树上操作暴力
- Codeforces Round #275 (Div. 1) D Random Function and Tree 树形dp
- Codeforces Round #358 (Div. 2) C. Alyona and the Tree 水题
- Codeforces Round #358 (Div. 2)-C. Alyona and the Tree(树形dp)
- Codeforces Round #263 (Div. 2) D. Appleman and Tree(树形DP)
- Codeforces Round #263 Div.1 B Appleman and Tree --树形DP【转】
- Codeforces Round #430 (Div. 2) C. Ilya And The Tree 树dp 统计
- Codeforces Round #382 (Div. 2) A. Ostap and Grasshopper
- Codeforces Round #430 (Div. 2) C. Ilya And The Tree dfs+set
- Codeforces Round #379 (Div. 2) E. Anton and Tree
- VK Cup 2016 - Round 1 (Div. 2 Edition) C. Bear and Forgotten Tree 3
- Codeforces Round #395 (Div. 2) C. Timofey and a tree (树的基础应用)
- [CF735E/736C]Ostap and Tree
- Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) E. Tree Folding 拓扑排序
- Codeforces Round #395 (Div. 2) C. Timofey and a tree(树的基础应用)
- Codeforces Round #264 (Div. 2) E. Caisa and Tree 树上操作暴力
- Codeforces Round #263 (Div. 1) B. Appleman and Tree( 树形DP )
- Codeforces Round #263 (Div. 1) B. Appleman and Tree(给一棵树,每个点为白色或黑色,切断一些边,使得每个连通块有且仅有一个黑点,问划分方案数。)