题意:给你一个有n个节点的树,每个节点的安全级别为1-m,但不是数字越大安全性越好,安全性最高为k,当一个节点安全性为k,和他相邻的节点的安全性可为(1....k-1),只有最多x个节点的安全性为k,问有多少分配方案
思路:树形dp,dp[i][j][x]表示以i为根的树有j个k安全性的时候,这个节点为0(即比k小),为1(为k),为2(比k大)的时候方案树
当我为0时,我的子节点可为 0,1,2,为1时,可为 0,为2时,可为0,2
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll mod=1e9+7; 5 const int N=1e5+100; 6 7 vector<int > g[N]; 8 ll dp[N][12][4]; 9 ll a[N]; 10 int n,m; 11 ll Ma,x; 12 ll b[12][4]; 13 int vis[N]; 14 15 void dfs(int u,int fa){ 16 //cout<<u<<" "<<fa<<endl; 17 dp[u][0][0]=Ma-1; 18 dp[u][1][1]=1; 19 dp[u][0][2]=m-Ma; 20 a[u]=1; 21 vis[u]=1; 22 for(int i=0;i<g[u].size();i++){ 23 int v=g[u][i]; 24 if(v==fa||vis[v]) continue ; 25 dfs(v,u); 26 memset(b,0,sizeof(b)); 27 // cout<<u<<" "<<v<<" "<<a[u]<<" "<<a[v]<<endl; 28 for(int j=0;j<=a[u];j++) 29 for(int k=0;k<=a[v];k++){ 30 if(j+k>x) continue; 31 b[j+k][0]=(b[j+k][0]+dp[u][j][0]*(dp[v][k][0]+dp[v][k][1]+dp[v][k][2])%mod)%mod; 32 b[j+k][1]=(b[j+k][1]+dp[u][j][1]*(dp[v][k][0])%mod); 33 b[j+k][2]=(b[j+k][2]+dp[u][j][2]*(dp[v][k][0]+dp[v][k][2])%mod)%mod; 34 // cout<<b[j+k][0]<<" "<<b[j+k][1]<<" "<<b[j+k][2]<<endl; 35 } 36 //cout<<"#"<<a[u]<<" "<<a[v]<<" "<<x<<endl; 37 a[u]=min(x,a[u]+a[v]); 38 // cout<<"@"<<a[u]<<endl; 39 for(int j=0;j<=a[u];j++){ 40 dp[u][j][0]=b[j][0]; 41 dp[u][j][1]=b[j][1]; 42 dp[u][j][2]=b[j][2]; 43 } 44 } 45 return ; 46 } 47 48 int main(){ 49 scanf("%d%d",&n,&m); 50 for(int i=1;i<n;i++){ 51 int u,v; 52 scanf("%d%d",&u,&v); 53 g[u].push_back(v); 54 g[v].push_back(u); 55 } 56 scanf("%d%d",&Ma,&x); 57 dfs(1,0); 58 int sum=0; 59 for(int i=0;i<=x;i++){ 60 for(int j=0;j<3;j++) 61 sum=(sum+dp[1][i][j])%mod; 62 } 63 cout<<sum<<endl; 64 }