AtCoder Beginner Contest 207 F - Tree Patrolling(树上背包)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 207 F - Tree Patrolling(树上背包)相关的知识,希望对你有一定的参考价值。
定义 f [ i ] [ j ] [ s t a = 0 / 1 / 2 ] f[i][j][sta=0/1/2] f[i][j][sta=0/1/2]表示 i i i的子树中有 j j j个节点受到保护
当 s t a = 0 sta=0 sta=0时,节点 i i i和他的直接儿子都没有放置保安
当 s t a = 1 sta=1 sta=1时,不管儿子怎样,反正点 i i i放置了保安
当 s t a = 2 sta=2 sta=2时,自己没有放置保安,但至少存在一个直接儿子放置了保安
转移方程就像树上背包那样类似的转移即可
特别的当之前自己的状态为 0 0 0且儿子的状态为 1 1 1时,那么自己的状态就转化为 2 2 2,且自己也被保安所保护
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
const int maxn = 3009;
int f[maxn][maxn][3],temp[maxn][3],a[maxn],siz[maxn],n;
vector<int>vec[maxn];
void dfs(int u,int fa)
{
siz[u] = 1;
f[u][0][0] = f[u][1][1] = 1;
for(auto v:vec[u] )
{
if( v==fa ) continue;
dfs( v,u );
for(int j=siz[u];j>=0;j--)
for(int q=siz[v];q>=0;q--)
for(int z1=0;z1<=2;z1++)//0表示自己和儿子没人放保安,1表示自己放了,2表示儿子放了
for(int z2=0;z2<=2;z2++)
{
int z = z1, x = j+q;
if( z1==0 && z2==1 ) z = 2, x++;
else if( z1==1 && z2==0 ) x++;
temp[x][z] = ( temp[x][z]+1ll*f[u][j][z1]*f[v][q][z2]%mod )%mod;
}
siz[u] += siz[v];
for(int j=0;j<=siz[u];j++)
for(int q=0;q<=2;q++)
{
f[u][j][q] = temp[j][q];
temp[j][q] = 0;
}
}
}
signed main()
{
cin >> n;
for(int i=1;i<n;i++)
{
int x,y; cin >> x >> y;
vec[x].push_back( y ); vec[y].push_back( x );
}
dfs( 1,0 );
for(int i=0;i<=n;i++) cout << ( 1ll*f[1][i][0]+f[1][i][1]+f[1][i][2] )%mod << endl;
}
以上是关于AtCoder Beginner Contest 207 F - Tree Patrolling(树上背包)的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Beginner Contest 115 题解