P3914-染色计数【树形dp】

    xiaoxiao2023-10-21  180

    正题

    题目链接:https://www.luogu.org/problemnew/show/P3914


    题目大意

    n n n个点每个点有些可以染的颜色,要求相邻颜色不相同,方案总数。


    解题思路

    树形 d p dp dp,定义 f x , i f_{x,i} fx,i表示点 x x x的染颜色 i i i的方案数。然后定义 z x = ∑ i = 1 m f x i z_x=\sum_{i=1}^mf_{x_i} zx=i=1mfxi

    然后显然动态转移方程 f x , i = z y − f y , i ( x − > y ) f_{x,i}=z_y-f_{y,i}(x->y) fx,i=zyfy,i(x>y)


    c o d e code code

    #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int XJQ=1e9+7,N=5001; int tot,n,m,f[N][N],z[N],ls[N]; struct node{ int to,next; }a[2*N]; void addl(int x,int y) { a[++tot].to=y; a[tot].next=ls[x]; ls[x]=tot; } void dp(int x,int fa) { for(int i=ls[x];i;i=a[i].next) { int y=a[i].to; if(y==fa) continue; dp(y,x); int k=1; for(int j=1;j<=m;j++) f[x][j]=1ll*f[x][j]*((z[y]-f[y][j]+XJQ)%XJQ)%XJQ; } for(int j=1;j<=m;j++) (z[x]+=f[x][j])%=XJQ; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ int k,x;scanf("%d",&k); for(int j=1;j<=k;j++) scanf("%d",&x),f[i][x]=1; } for(int i=1;i<n;i++){ int x,y;scanf("%d%d",&x,&y); addl(x,y);addl(y,x); } dp(1,0); printf("%d",z[1]); }
    最新回复(0)