zoukankan      html  css  js  c++  java
  • 51Nod1353 树

    题目看这里

    题意很简单,大概是有多少种删边方法使得每一块大小不小于k

    我们设一个树形dp,f[i][j]表示i的子树中,i所在联通块的大小为j的方案数有多少

    特别的,我们用f[i][0]表示∑f[i][j] (j>=k)

    那么可以写出以下转移:

    f[x][i+j]+=f[x][i]*f[v][j] (j>0)

    f[x][i]=f[x][i]*f[v][0]

    答案就是f[root][0]

    #include<vector>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define LL long long
    #define M 1000000007
    using namespace std;
    struct edge{ int v,nt; } G[4010];
    int h[2010],f[2010][2010],sz[2010],n,m,cnt=0;
    inline void ad(int& x,LL y){ x=(x+y)%M; }
    inline void adj(int x,int y){
        G[++cnt]=(edge){y,h[x]}; h[x]=cnt;
        G[++cnt]=(edge){x,h[y]}; h[y]=cnt;
    }
    void dp(int x,int p){
        f[x][1]=sz[x]=1;
        for(int v,i=h[x];i;i=G[i].nt)
            if((v=G[i].v)!=p){
                dp(v,x);
                for(int i=sz[x];i;--i){
                    for(int j=sz[v];j;--j)
                        ad(f[x][i+j],(LL)f[x][i]*f[v][j]);
                    f[x][i]=(LL)f[x][i]*f[v][0]%M;
                }
                sz[x]+=sz[v];
            }
        for(int i=m;i<=sz[x];++i) ad(f[x][0],f[x][i]);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int x,y,i=1;i<n;++i,adj(x,y)) scanf("%d%d",&x,&y);
        dp(1,0);
        printf("%d
    ",f[1][0]);
    }

  • 相关阅读:
    大白话五种IO模型
    test
    shutil模块(了解)
    isinstance和issubclass
    变量的三个特征
    匿名函数
    javascript location 对象
    select元素javascript常用操作
    设置mysql的用户权限
    jquery
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477089.html
Copyright © 2011-2022 走看看