题目描述
有一颗\(N\)个节点的树,节点用\(1,2,\cdots,N\)编号。你要给它染色,使得相邻节点的颜色不同。有\(M\)种颜色,用\(1,2,\cdots,M\)编号。每个节点可以染\(M\)种颜色中的若干种,求不同染色方案的数量除以(\(10^9 + 7\))的余数。
输入输出格式
输入格式:
第1 行,2 个整数\(N,M\)。
接下来\(N\)行,第\(i\)行表示节点\(i\)可以染的颜色。第1个整数\(k_i\),表示可以染的颜色数量。接下来\(k_i\)个整数,表示可以染的颜色编号。
最后\(N - 1\)行,每行2个整数\(A_i,B_i\),表示边\((A_i,B_i)\)。
树形dp
dp方程
\(f[u][i]*=∑f[to][x]\) \(x!=i\)
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=5000+10;
int f[maxn][maxn];//点i染成j的方案数
int sum[maxn],head[maxn];
int size=0;
int n,m;
struct edge
{
int to,next,val;
}e[maxn<<1];
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(x=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
void addedge(int u,int v)
{
e[++size].to=v;
e[size].next=head[u];
head[u]=size;
}
void dfs(int u,int fa)
{
for(int i=head[u];i;i=e[i].next)
{
int to=e[i].to;
if(to==fa)continue;
dfs(to,u);
for(int i=1;i<=m;i++)
{
f[u][i]=((long long)f[u][i]*(sum[to]-f[to][i]+mod)%mod)%mod;
}
}
for(int i=1;i<=m;i++)
sum[u]+=f[u][i],sum[u]%=mod;
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
{
int k=read();
for(int j=1;j<=k;j++)
f[i][read()]=1;
}
for(int i=1;i<n;i++)
{
int u=read(),v=read();
addedge(u,v),addedge(v,u);
}
dfs(1,0);
printf("%d",sum[1]);
return 0;
}