Solution of CF855C
Powerless233 · · 题解
Description
原题的翻译多少有点问题。搬一下 一扶苏一 在题解中的翻译:
给你一个树,可以染
Analysis
读题意,树上方案数统计问题,显然树形 dp 。
考虑什么因素会对答案造成影响:子树内 已经染的特殊颜色数量,当前点编号 与特殊颜色编号的关系 。
与特殊编号的关系无非
那么状态就很显然了。
设
接下来,就是一般的树形背包了。
根据题意,有状态转移方程:
(其中,
- 当前节点编号
< k ,那么儿子随便取:
- 当前节点编号
= k ,那么儿子编号<k :
- 当前节点编号
> k ,那么儿子只有k 不能取:
边界情况:
Notice
-
注意取模。
-
背包的时候下标可能会重复,记得先记下原子树的信息再更新。
Code
#include<bits/stdc++.h>
#define LL long long
#define inf 0x3f3f3f3f
using namespace std;
inline LL read(){
LL res=0,fl=1;
char ch=getchar();
while(!(ch>='0' && ch<='9')){if(ch=='-')fl=-1;ch=getchar();}
while(ch>='0' && ch<='9')res=(res<<3)+(res<<1)+ch-'0',ch=getchar();
return res*fl;
}
inline LL max(LL a,LL b){return a>b?a:b;}
inline LL min(LL a,LL b){return a<b?a:b;}
inline void swap(int &a,int &b){int c;c=a;a=b;b=c;}
const int MAXN=1e5+5,MAXK=10+5,mod=1e9+7;
int n,m,k,p,ans=0,si[MAXN],f[MAXN][MAXK][3],g[MAXN][MAXK];
vector<int> e[MAXN];
inline void Tree_dp(int x,int fa){
si[x]=1;
f[x][0][0]=k-1;
f[x][1][1]=1;
f[x][0][2]=m-k;
for(int i=0;i<e[x].size();i++){
int y=e[x][i];
if(y!=fa){
Tree_dp(y,x);
int up1=min(si[x],p),up2;
for(int j=0;j<=up1;j++)
for(int c=0;c<=2;c++)
g[j][c]=f[x][j][c],f[x][j][c]=0;
for(int j=0;j<=up1;j++){
up2=min(si[y],p-j);
for(int l=0;l<=up2;l++){
f[x][j+l][0]=(f[x][j+l][0]+1LL*g[j][0]%mod*((f[y][l][0]+f[y][l][1])%mod+f[y][l][2])%mod)%mod;
f[x][j+l][1]=(f[x][j+l][1]+1LL*g[j][1]%mod*f[y][l][0]%mod)%mod;
f[x][j+l][2]=(f[x][j+l][2]+1LL*g[j][2]%mod*(f[y][l][0]+f[y][l][2])%mod)%mod;
}
}
si[x]+=si[y];
}
}
}
int main() {
int x,y;
n=read(),m=read();
for(int i=1;i<n;i++){
x=read(),y=read();
e[x].push_back(y);
e[y].push_back(x);
}
k=read(),p=read();
Tree_dp(1,0);
for(int i=0;i<=p;i++)
for(int j=0;j<=2;j++)
ans=(ans+f[1][i][j])%mod;
cout<<ans<<'\n';
return 0;
}