zoukankan      html  css  js  c++  java
  • Luogu3914 染色计数

    Description

    link

    给定一棵 (n) 个点的树,树上的每个点可以涂 (m) 种颜色的中的几种

    规定相邻的两个点涂的颜色不一样,求方案数

    (n,m le 5000)

    Solution

    定义状态:

    (f_{x,y}) 为点 (x) 涂颜色 (y) 的时候的子树里的方案数

    那么答案就是

    [sum_{i=1&&iin {col_1}}^m f_{1,i} ]

    转移就是把每个儿子上面颜色不一样的求和乘起来

    我们发现这个做法是 (O(n^3)) 的,并不能通过

    然后我们优化一下这个转移,把每个儿子的方案求个和

    对应乘的时候直接减掉那个颜色就成了

    Code

    #include<bits/stdc++.h>
    using namespace std;
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	const int mod=1e9+7,N=5010;
    	int n,m,head[N],cnt;
    	struct node{
    		int to,nxt;
    	}e[N<<1];
    	inline void add(int u,int v)
    	{
    		e[++cnt].to=v; e[cnt].nxt=head[u];
    		return head[u]=cnt,void();
    	}
    	int sum[N],f[N][N];
    	inline void dfs(int x,int fa)
    	{
    		for(int i=head[x];i;i=e[i].nxt)
    		{
    			int t=e[i].to; 
    			if(t==fa) continue; dfs(t,x);
    			for(int j=1;j<=m;++j) 
    			{
    				f[x][j]=1ll*f[x][j]*((sum[t]-f[t][j]+mod)%mod)%mod;	
    			}
    		}
    		for(int i=1;i<=m;++i) sum[x]=(sum[x]+f[x][i])%mod; 
    		return ;
    	}
    	signed main()
    	{
    		n=read(); m=read();
    		for(int tmp,i=1;i<=n;++i)
    		{
    			tmp=read(); while(tmp--) f[i][read()]=1;
    		}
    		for(int i=1,u,v;i<n;++i) u=read(),v=read(),add(u,v),add(v,u);
    		dfs(1,0); printf("%d
    ",sum[1]);
    		return 0;
    	}
    }
    signed main(){return yspm::main();}
    
  • 相关阅读:
    心跳机制
    C++虚继承和虚基类
    STL,ATL与WTL
    C# Task的暂停与终止
    C#继承
    C#线程同步问题
    CourtAi发布配置文件修改说明
    阿里云虚拟主机https化步骤第一篇,申请证书(笔记)
    linux 服务器重启指令
    .net core 发布到iis问题 HTTP Error 500.30
  • 原文地址:https://www.cnblogs.com/yspm/p/13234381.html
Copyright © 2011-2022 走看看