题解:AT_abc036_d [ABC036D] 塗り絵

题意

有一棵由 \(N\) 个点 \(N-1\) 条边构成的树,求出树上每个点染成白色或黑色,但相邻两个点不能同时染成黑色的染色方案数量,并取模 \(10^9+7\)

思路

对于这种求合法方案数的题目,一般可以考虑 \(dp\) 。设 \(dp_{i,1}\) 表示第 \(i\) 个节点为染成黑色的方案数。设 \(dp_{i,0}\) 表示第 \(i\) 个节点为染成白色的方案数。

再利用乘法原理,可得出动态转移方程。

\[dp_{i,1} \gets dp_{i,1} \times dp_{j,0}, \]

\[dp_{i,0} \gets dp_{i,0} \times (dp_{j,0}+dp_{j,1}). \]

然后输出 \(dp_{1,1}+dp_{1,0}\) 即可。

记得取模!!!

code

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7;
const int N=100005;
int n,u,v,dp[N][5],tot=1,head[N];
struct op
{
	int to,next;
}arr[N<<1];
void edge(int x,int y){
	arr[tot].to=y;
	arr[tot].next=head[x];
	head[x]=tot++;
}
void dfs(int x,int fa){
	dp[x][0]=1,dp[x][1]=1;//初始化
	for(int i=head[x];i;i=arr[i].next){
		int y=arr[i].to;
		if(fa==y)continue;
		dfs(y,x);
		dp[x][0]*=dp[y][0]+dp[y][1];//动态转移方程
		dp[x][1]*=dp[y][0];//动态转移方程
		dp[x][1]%=mod;
		dp[x][0]%=mod;
	}
}
signed main(){
    scanf("%lld",&n);
	for(int i=1;i<n;i++){
        scanf("%lld%lld",&u,&v);
		edge(u,v),edge(v,u);//建边
	}//输入
	dfs(1,0);
    printf("%lld\n",(dp[1][0]+dp[1][1])%mod);//输出
	return 0;
} 
posted @ 2025-11-02 19:25  xthought  阅读(4)  评论(0)    收藏  举报