您的位置:首页 > 其它

JZOJ 5426 Galo

2017-10-30 22:38 204 查看

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
;
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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: