AtCoder Beginner Contest 207 F - Tree Patrolling(树上背包)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 207 F - Tree Patrolling(树上背包)相关的知识,希望对你有一定的参考价值。

LINK


定义 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 234

AtCoder Beginner Contest 115 题解

AtCoder Beginner Contest 154 题解

AtCoder Beginner Contest 103

AtCoder Beginner Contest 228

AtCoder Beginner Contest 242