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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值