zoukankan      html  css  js  c++  java
  • JSOI2018 潜入行动

    题目链接:戳我

    就是一个树形DP了.....
    我们设(f[i][j][0/1][0/1])表示当前点i,子树中一共放了j个,这个点是否放了,这个是否被覆盖了
    然后DP转移就很简单了(详细可以看代码QAQ)

    但是为什么这样子不是(nk^2)的......?
    我也不会啊,于是去看了看神仙的博客
    感觉他写得很详细啦qwq,我就不写了》》

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 102
    #define mod 1000000007
    using namespace std;
    int n,m,t,K,ans;
    int head[100010],siz[100010],f[100010][MAXN][2][2],tmp[MAXN][2][2];
    struct Edge{int nxt,to;}edge[200010];
    inline void add(int from,int to)
    {
        edge[++t].nxt=head[from],edge[t].to=to;
        head[from]=t;
    }
    inline void update(int &x,int y){x=(x+y)%mod;}
    inline void solve(int x,int pre)
    {
        siz[x]=1;
        f[x][0][0][0]=f[x][1][1][0]=1;
        for(int i=head[x];i;i=edge[i].nxt)
        {
        int v=edge[i].to;
        if(v==pre) continue;
        solve(v,x);
        for(int j=0;j<=siz[x]&&j<=K;j++)
            for(int k=0;k<=siz[v]&&j+k<=K;k++)
            {
                update(tmp[j+k][0][0],1ll*f[x][j][0][0]*f[v][k][0][1]%mod);
                update(tmp[j+k][0][1],1ll*f[x][j][0][0]*f[v][k][1][1]%mod);
                update(tmp[j+k][0][1],1ll*f[x][j][0][1]*(f[v][k][0][1]+f[v][k][1][1])%mod);
                update(tmp[j+k][1][0],1ll*f[x][j][1][0]*(f[v][k][0][0]+f[v][k][0][1])%mod);
                update(tmp[j+k][1][1],1ll*f[x][j][1][0]*(f[v][k][1][0]+f[v][k][1][1])%mod);
                int cur_ans=0;
                update(cur_ans,f[v][k][0][0]);
                update(cur_ans,f[v][k][0][1]);
                update(cur_ans,f[v][k][1][0]);
                update(cur_ans,f[v][k][1][1]);
                update(tmp[j+k][1][1],1ll*f[x][j][1][1]*cur_ans%mod);
            }
            siz[x]+=siz[v];
            for(int j=0;j<=siz[x]&&j<=K;j++)
            {
                f[x][j][0][0]=tmp[j][0][0];
                f[x][j][0][1]=tmp[j][0][1];
                f[x][j][1][0]=tmp[j][1][0];
                f[x][j][1][1]=tmp[j][1][1];
                tmp[j][0][0]=tmp[j][0][1]=tmp[j][1][0]=tmp[j][1][1]=0;
            }
        }
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d",&n,&K);
        for(int i=1;i<n;i++)
        {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y),add(y,x);
        }
        solve(1,0);
        ans=(f[1][K][0][1]+f[1][K][1][1])%mod;
        printf("%d
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    linux 和 ubuntu 修改主机名
    Linux删除用户
    ubuntu更新源
    python连接mysql
    用于迭代器的yield return
    Tuple类型
    Action 和 Func
    用iDSDT制作声显卡DSDT
    C#“同步调用”、“异步调用”、“异步回调”
    读懂IL代码就这么简单
  • 原文地址:https://www.cnblogs.com/fengxunling/p/11127028.html
Copyright © 2011-2022 走看看