【51nod 1353】 树(树形DP)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Coldfresh/article/details/83184493

基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
今天小a在纸上研究树的形态,众所周知的,有芭蕉树,樟树,函树,平衡树,树套树等等。那么小a今天在研究的就是其中的平衡树啦。

小a认为一棵平衡树的定义为一个n个点,从1到n编号,n-1条边,且任意两点间一定存在唯一一条简单路径,且n>=k。

现在小a看到一棵很大很大的树,足足有n个节点,这里n一定大于等于k!为了方便起见,它想把这个树删去某些边,使得剩下的若干个联通块都满足是平衡树。这时,小b走过来,不屑一顾的说,如果我一条边都不删,那么也算一棵平衡树咯。

小a对于小b的不屑感到很不爽,并问小b,你能算出我删边的方案总数使得满足我的条件吗?两个删边的方案A,B不同当且仅当存在某一条边属于集合A且不属于集合B,或者存在某一条边属于集合B且不属于集合A。为了让你方便,你只要告诉我答案对1000000007(1e9+7)取模就行了。

小b犯了难,找到了身为程序猿的你。

Hint:

样例解释,

第一种方案为不删边,

第二种方案为删去2 3这一条边,

第三种方案为删去3 4这一条边。

Input
第一行读入两个正整数n,k(1<=k<=n<=2000)。
接下来n-1行,每行两个正整数A,B ( 1<= A,B<= n),表示A与B有一条边相连,题目保证在不删任何一条边的情况下是一棵平衡树。
Output
一个整数,表示答案对1000000007(1e9+7)取模后的值。
Input示例
5 2
1 2
2 3
3 4
4 5
Output示例
3
思路:设 d p [ u ] [ i ] dp[u][i] 表示以u为根的子树里,与u相连的联通快大学为i是,其他的联通快大小是大于等于 k k 时的种数。特别地,我们把 d p [ u ] [ 0 ] dp[u][0] 设为,以u为根的子树里,联通快的大小是大于等于k的所有种树,如果我们设整棵树的根为1,那么答案就是 d p [ 1 ] [ 0 ] dp[1][0] .
那么我们就根据这个就饿可以写了。
代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#define maxn 2005
#define ll long long
#define mod 1000000007
using namespace std;
int n,k;
int head[maxn],to[maxn<<1],_next[maxn<<1],edge;
void addEdge(int x,int y)
{
    to[++edge]=y,_next[edge]=head[x],head[x]=edge;
    to[++edge]=x,_next[edge]=head[y],head[y]=edge;
}
ll dp[maxn][maxn];
int _size[maxn];
void dfs(int u,int last)
{
    dp[u][1]=_size[u]=1;
    for(int i=head[u];i;i=_next[i])
    {
        int v=to[i];
        if(v==last)continue;
        dfs(v,u);
        for(int j=_size[u];j;j--)
        {
            for(int l=1;l<=_size[v];l++)
                dp[u][j+l]=(dp[u][j+l]+dp[v][l]*dp[u][j])%mod;
            dp[u][j]=dp[u][j]*dp[v][0]%mod;
        }
        _size[u]+=_size[v];
    }
    for(int i=k;i<=_size[u];i++)
        dp[u][0]=(dp[u][0]+dp[u][i])%mod;
}
int main()
{
    cin>>n>>k;
    int x,y;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        addEdge(x,y);
    }
    dfs(1,0);
    cout<<dp[1][0]<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Coldfresh/article/details/83184493
今日推荐