Codeforces-Gym 101505F:Tree Stands(树形DP)

版权声明:http://blog.csdn.net/Mitsuha_。 https://blog.csdn.net/Mitsuha_/article/details/82226505

传送门

思路:树形DP。

d [ i ] [ j ] 表示以 i 为根的子树内,放了 j 人的方案数。

对于以 i 为根节点的子树,有3种状态。

0:在 i 这个节点不放人的合法方案数。
1:在 i 这个节点放人的合法方案数。
2:在 i 这个节点放人的不合法方案数。即在 i 这个节点放人,但是儿子节点上都没有人, i 这个点是孤立的,但所有儿子的状态都是合法的。

#include<bits/stdc++.h>
const int MAX=1e6+10;
const int MOD=1e9+7;
using namespace std;
typedef long long ll;
vector<int>e[300];
ll d[210][210][3];
int n,m;
void dfs(int k,int fa)
{
    d[k][0][0]=1;
    d[k][1][2]=1;
    for(int i=0;i<e[k].size();i++)
    {
        int nex=e[k][i];
        if(nex==fa)continue;
        dfs(nex,k);

        for(int j=m;j>=1;j--)
        {
            for(int r=0;r<j;r++)//枚举儿子节点放的人数,r<j确保儿子节点至少放一个人
            {
                d[k][j][0]+=d[k][r][0]*((d[nex][j-r][0]+d[nex][j-r][1])%MOD)%MOD;
                d[k][j][1]+=d[k][r][1]*((d[nex][j-r][2]+d[nex][j-r][1]+d[nex][j-r][0])%MOD)%MOD;
                d[k][j][1]+=d[k][r][2]*((d[nex][j-r][2]+d[nex][j-r][1])%MOD)%MOD;


                d[k][j][0]%=MOD;
                d[k][j][1]%=MOD;
            }

        }
        for(int j=m;j>=2;j--)//更新当前节点孤立的方案数
        {
            for(int r=1;r<j;r++)
            {
                d[k][j][2]+=d[k][r][2]*d[nex][j-r][0]%MOD;
                d[k][j][2]%=MOD;
            }
        }
    }
}
int main()
{

    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++)e[i].clear();
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            e[x].push_back(y);
            e[y].push_back(x);
        }
        memset(d,0,sizeof d);
        dfs(1,0);
        printf("%lld\n",(d[1][m][0]+d[1][m][1])%MOD);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Mitsuha_/article/details/82226505