[BZOJ5314][树形背包]JSOI2018:潜入行动

BZOJ5314

sb树形dp
如果你做JSOI了还做不来这个(复杂度不会证就算了,我也不会,好像是 O ( n k 2 ) O(nk^2) O(nk2))你就该去反思一下了

Code:

#include<bits/stdc++.h>
#define mod 1000000007
#define ll long long
using namespace std;
inline int read(){
	int res=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
	return res*f;
}
const int N=1e5+5;
int n,k,f[N][105][2][2],siz[N];
ll g[105][2][2];
int pt[N],vis[N<<1],head[N<<1],nxt[N<<1],tot=0;
inline void add(int x,int y){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
inline int ad(int &a,ll b){return (a+((int)(b%mod)))%mod;}
void dfs(int v){
    pt[v]=siz[v]=1;
    f[v][0][0][0]=f[v][1][1][0]=1;
    for(int i=head[v];i;i=nxt[i]){
        int y=vis[i];
        if(pt[y])continue;
        dfs(y);
        for(int i=0;i<=min(siz[v],k);++i){
          g[i][0][0]=f[v][i][0][0],f[v][i][0][0]=0;
          g[i][0][1]=f[v][i][0][1],f[v][i][0][1]=0;
          g[i][1][0]=f[v][i][1][0],f[v][i][1][0]=0;
          g[i][1][1]=f[v][i][1][1],f[v][i][1][1]=0;
        }
        for(int i=0;i<=min(siz[v],k);++i)
            for(int j=0;j<=min(siz[y],k-i);++j){
                f[v][i+j][0][0]=ad(f[v][i+j][0][0],(ll)g[i][0][0]*(ll)f[y][j][0][1]);
                f[v][i+j][1][0]=ad(f[v][i+j][1][0],(ll)g[i][1][0]*(ll)(f[y][j][0][0]+f[y][j][0][1]));
                f[v][i+j][0][1]=ad(f[v][i+j][0][1],(ll)g[i][0][0]*(ll)f[y][j][1][1]+(ll)g[i][0][1]*(ll)(f[y][j][0][1]+f[y][j][1][1]));
                f[v][i+j][1][1]=ad(f[v][i+j][1][1],(ll)g[i][1][0]*(ll)(f[y][j][1][1]+f[y][j][1][0])+(ll)g[i][1][1]*(ll)((ll)(f[y][j][0][0]+f[y][j][0][1])+(ll)(f[y][j][1][1]+f[y][j][1][0])));

            }
        siz[v]+=siz[y];
    }
}
main(){
	n=read();k=read();
    for(int x,y,i=1;i<n;i++){x=read(),y=read();add(x,y);add(y,x);}
    dfs(1);
    cout<<((f[1][k][1][1]+f[1][k][0][1])%mod)<<"\n";
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值