JZOJ 5426 Galo

来源:互联网 发布:owncloud php版本 编辑:程序博客网 时间:2024/06/12 19:13

Galo

Description

给出一棵以1号点为根的n个点的有根数,除了根节点以外,每个节点i都有一个果子,美味度为wi
如果摘下了i号果子,那么i的子树中的果子以及i到根的路径上的其他果子都会死掉,都不能摘。
最多能摘k个果子,问所摘果子的美味度之和的最大值是多少。

Data Constraint

n*k<=107
wi<=105

Solution

经典例题,其实也没什么好讲的,就是树型依赖动态规划。
s[i]表示以i为根的子树大小。
d[i]表示dfs序的第i位的节点。
转移方程式如下
f[i][l]=max(max(f[i+1][l],f[i+s[d[i]]][l]),f[i+s[d[i]]][l-1]+w[d[i]])
不会树型依赖动态规划请点这里
树型依赖动态规划

Code

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define fo(i,j,l) for(int i=j;i<=l;i++)#define fd(i,j,l) for(int i=j;i>=l;i--)using namespace std;typedef long long ll;const long long N=2e7+2e3,M=N/2;ll f[N];int ne[M],lb[M],la[M],s[M],d[M],w[M];int n,m,j,k,l,i,o,a,b;void llb(int a,int b){ne[++o]=la[a]; la[a]=o; lb[o]=b;}int de(int a,int b){return (a-1)*(k+1)+b+1;}ll max(ll a,ll b){if(a>b)return a;else return b;}int main(){    freopen("galo.in","r",stdin);    freopen("galo.out","w",stdout);    cin>>n>>k; int kk=k+1;    fo(i,2,n){        scanf("%d%d",&a,&b);        llb(a,i); w[i]=b;    }    int r,t;    d[k=1]=1;    s[1]=1;    s[0]=0;    for(f[1]=r=1;r;){        t=f[r];        s[t]+=s[f[r+1]];        if(la[t]){            f[++r]=lb[la[t]]; d[++k]=f[r];            la[t]=ne[la[t]]; s[f[r]]=1; f[r+1]=0;        }else r--;    }    w[1]=0;    fo(i,1,n)f[de(i,0)]=0;    k=kk;    fd(i,n,1)    fo(l,1,k)    f[de(i,l)]=    max(max(f[de(i+1,l)],f[de(i+s[d[i]],l)]),f[de(i+s[d[i]],l-1)]+w[d[i]]);    ll ans=0;    fo(i,1,k)ans=max(ans,f[de(1,i)]);    printf("%lld",ans);}
原创粉丝点击