101505F Tree Stands [樹形揹包]
阿新 • • 發佈:2019-01-25
題意:給你一棵樹,k個人,每顆樹上只能安排一個人,每個人必須有另一個人相鄰,問所有的方案總數。
題解:對於每一個節點,我們記錄當這個節點包含k個人的時候,該節點是空的,或者該節點相連的只有一個人,或者該節點相連的有一個以上,這三種情況。然後揹包轉移。
AC程式碼:
#include<stdio.h> #include<vector> #include<string.h> #define mod 1000000007 using namespace std; typedef long long ll; ll dp[205][205][3]; vector<ll>vt[205]; ll ans,n,k; void dfs(ll u,ll fa) { dp[u][0][0]=1; dp[u][1][1]=1; for(ll i=0;i<vt[u].size();i++) { ll to=vt[u][i]; if(to==fa)continue; dfs(to,u); for(ll s=k;s>=0;s--) { ll now0=0,now1=0,now2=0; for(ll j=0;j<=s;j++) { now0+=dp[u][j][0]*(dp[to][s-j][0]+dp[to][s-j][2])%mod; now1+=dp[u][j][1]*(dp[to][s-j][0])%mod; now2+=dp[u][j][1]*(dp[to][s-j][1]+dp[to][s-j][2]); now2+=dp[u][j][2]*(dp[to][s-j][0]+dp[to][s-j][1]+dp[to][s-j][2])%mod; now0%=mod; now1%=mod; now2%=mod; } dp[u][s][0]=now0;dp[u][s][1]=now1;dp[u][s][2]=now2; } } } int main() { while(~scanf("%lld%lld",&n,&k)) { memset(dp,0,sizeof(dp)); ans=0; for(ll i=1;i<=n;i++)vt[i].clear(); for(ll i=0;i<n-1;i++) { ll u,v; scanf("%lld%lld",&u,&v); vt[u].push_back(v); vt[v].push_back(u); } dfs(1,-1); printf("%lld\n",(dp[1][k][0]+dp[1][k][2])%mod); } }