题意:
给出一棵树,要将树上的点染成白色或者黑色,有一个限制条件,任意两个黑色的点的LCA的颜色也必须是黑色,求染色的方案数。
题解:
设dp[i]表示以i为根节点的子树的至少有一个黑点的方案数,空集就是dp[i]+1
1.若点u为黑点,那么子节点怎么染色都可以,dp[u]=∏(dp[v]+1)
2.若u为白色的点,那么子节点至少有一个黑点,dp[u]+=dp[v]
最后答案就是ans=dp[1]+1;
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int mod=1e9+7;
const int MAXN=1e6+5;
int head[MAXN];
int cnt=0;
ll dp[MAXN];
struct node
{
int to;
int next;
}e[MAXN<<1];
void add(int u,int v)
{
e[cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt++;
}
void dfs(int u,int f)
{
ll sum1=1;
ll sum2=0;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(v==f) continue;
dfs(v,u);
sum1=sum1*(dp[v]+1)%mod;
sum2=(sum2+dp[v])%mod;
}
dp[u]=sum1;
dp[u]=(dp[u]+sum2)%mod;
}
int main()
{
int n;
cin>>n;
memset(head,-1,sizeof head);
int u,v;
for(int i=1;i<=n-1;i++)
{
cin>>u>>v;
add(u,v);
add(v,u);
}
dfs(1,-1);
ll ans=(dp[1]+1)%mod;
printf("%lld\n",ans);
}