P3914染色计数

题目描述

有一颗(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;
} 
原文地址:https://www.cnblogs.com/DriverBen/p/10535887.html