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();}
    
  • 相关阅读:
    SGU 271 Book Pile (双端队列)
    POJ 3110 Jenny's First Exam (贪心)
    HDU 4310 Hero (贪心)
    ZOJ 2132 The Most Frequent Number (贪心)
    POJ 3388 Japanese Puzzle (二分)
    UVaLive 4628 Jack's socks (贪心)
    POJ 2433 Landscaping (贪心)
    CodeForces 946D Timetable (DP)
    Android Studio教程从入门到精通
    Android Tips – 填坑手册
  • 原文地址:https://www.cnblogs.com/yspm/p/13234381.html
Copyright © 2011-2022 走看看