题目大意
给你一棵树,可以染m种颜色,现定义一种特殊的颜色K,一棵树上最多能有x个特殊颜色。如果一个节点为特殊颜色,那么他相邻的节点的值只能选比K小的颜色,问一共有多少种染色方案。
分析
不难想出这是一个树型dp,用dp[i][j][k]表示考虑第i个点所选的颜色的种类为j,共用了k个特殊颜色。j的状态分别是0代表[1,K-1],1代表[K+1,m],2代表K。然后我们考虑如何转移。首先我们不难想到对于每种状态它是由之前哪种状态转移来的(见代码),对于k的枚举我们可以依次考虑一个点的所有儿子,然后每一次用当前儿子的值更新这个点的dp值。我们假设之前所有儿子和这个点自己一共选了k1个特殊颜色,而这个儿子及其子树选了k2个特殊颜色,这样就可以转移了。详见代码。
代码
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cctype> #include<cmath> #include<cstdlib> #include<queue> #include<ctime> #include<vector> #include<set> #include<map> #include<stack> using namespace std; #define li long long const li mod = 1e9+7; li n,m,x,sum,dp[101000][3][12],now[3][12]; vector<li>v[101000]; inline void dfs(li a,li fa){ dp[a][0][0]=m-x; dp[a][1][0]=x-1; dp[a][2][1]=1; for(li i=0;i<v[a].size();i++) if(v[a][i]!=fa){ dfs(v[a][i],a); memset(now,0,sizeof(now)); for(li k=0;k<=sum;k++) for(li k2=0;k2+k<=sum;k2++){ now[0][k+k2]=(now[0][k+k2]+(dp[a][0][k]* (dp[v[a][i]][0][k2]+dp[v[a][i]][1][k2]))%mod)%mod; now[1][k+k2]=(now[1][k+k2]+(dp[a][1][k]*(dp[v[a][i]][0][k2] +dp[v[a][i]][1][k2]+dp[v[a][i]][2][k2])%mod))%mod; now[2][k+k2]=(now[2][k+k2]+ (dp[a][2][k]*dp[v[a][i]][1][k2]%mod))%mod; } for(li k=0;k<=sum;k++){ dp[a][0][k]=now[0][k]; dp[a][1][k]=now[1][k]; dp[a][2][k]=now[2][k]; } } return; } int main(){ li i,j,k; scanf("%lld%lld",&n,&m); memset(dp,0,sizeof(dp)); for(i=1;i<n;i++){ li a,b; scanf("%lld%lld",&a,&b); v[a].push_back(b); v[b].push_back(a); } scanf("%lld%lld",&x,&sum); dfs(1,0); li ans=0; for(i=0;i<3;i++) for(j=0;j<=sum;j++) ans=(ans+dp[1][i][j])%mod; printf("%lld\n",ans); return 0; }
855C Helga Hufflepuff's Cup
原文地址:https://www.cnblogs.com/yzxverygood/p/9490192.html
时间: 2024-08-30 14:31:14