[ABC036D] 塗り絵 题解

题意

题面讲挺清楚的就不简化了。

思路

树上求方案数,很明显是树上 dp

\(dp_{i,0/1}\) 表示第 \(i\) 个点涂成白/黑色的方案数。

当前结点如果为白色,那么它的子节点涂成什么颜色都没关系,根据分步乘法原理,将它子结点涂成白/黑色的方案数之和乘起来即可;当前结点如果为黑色,那么它的子节点只能涂成白色,根据分步乘法原理,将它子结点涂成白色的方案数乘起来即可。如果 \(i\) 是叶子结点,那么 \(dp_{i,0}=dp_{i,1}=1\)

形式化的讲:

  • \(dp_{i,0}=\prod dp_{j,0}+dp_{j,1}\)
  • \(dp_{i,1}=\prod dp_{j,0}\)

其中 \(j\) 表示 \(i\) 的一个子结点。
记得取模。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7;
int n,m;
int head[200005],cnt=1;
int dp[100005][2];
int ans;
struct node{
    int to,next;
}edge[200005];
void add(int x,int y){
    edge[cnt].to=y;
    edge[cnt].next=head[x];
    head[x]=cnt++;
}
void dfs(int x,int fa){
    int num=0;
    dp[x][0]=1;
    dp[x][1]=1;
    for(int i=head[x];i;i=edge[i].next){
        int u=edge[i].to;
        if(u==fa) continue;
        num++;
        dfs(u,x);
        dp[x][0]*=(dp[u][0]+dp[u][1])%mod;
        dp[x][0]%=mod;
        dp[x][1]*=dp[u][0];
        dp[x][1]%=mod;
    }
}
signed main(){
    scanf("%lld",&n);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%lld%lld",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs(1,0);
    printf("%lld",(dp[1][0]+dp[1][1])%mod);
    return 0;
}
posted @ 2024-06-07 19:45  Linurve10  阅读(18)  评论(0)    收藏  举报