ans[u]:覆盖完u的子树需要的最少次数。
f[u]:花费最少次数覆盖完u的子树后,u还可以向上延伸的最大长度。
len[u]:从u开始可以向上延伸的最大长度。
正常情况下:
ans[u]+=ans[e[i].to]],f[u]=max(f[e[i].to])
若u为叶节点:
ans[u]=1,f[u]=len[u]
若到u时,f[e[i].to]刚好全部空了:
ans[u]+=ans[e[i].to],ans++,f[u]=len[u]
len[u]通过倍增可得,ans[u],f[u]树形dp即可。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int n,L,S,u;
int v[N],p[N][18],d[N],dis[N],len[N],f[N],ans[N];
int cnt,head[N];
struct edge{int next,to;}e[N<<1];
inline void add(int u,int v)
{
cnt++;
e[cnt].next=head[u];
e[cnt].to=v;
head[u]=cnt;
}
void dfs(int u)
{
for (register int i=1; (1<<i)<=d[u]; ++i) p[u][i]=p[p[u][i-1]][i-1];
for (register int i=head[u]; i; i=e[i].next)
{
d[e[i].to]=d[u]+1;
dis[e[i].to]=dis[u]+v[e[i].to];
p[e[i].to][0]=u;
dfs(e[i].to);
}
}
void dfs2(int u)
{
bool jay=false;
for (register int i=head[u]; i; i=e[i].next)
{
jay=true;
dfs2(e[i].to);
ans[u]+=ans[e[i].to];
f[u]=max(f[u],f[e[i].to]-1);
}
if (!jay)
{
f[u]=len[u];
ans[u]=1;
return;
}
if (!f[u])
{
f[u]=len[u];
ans[u]++;
}
}
signed main(){
scanf("%lld%lld%lld",&n,&L,&S);
for (register int i=1; i<=n; ++i) scanf("%lld",&v[i]);
for (register int i=2; i<=n; ++i) scanf("%lld",&u),add(u,i);
for (register int i=1; i<=n; ++i)
if (v[i]>S)
{
puts("-1");
return 0;
}
d[1]=1; dis[1]=v[1]; dfs(1);
for (register int i=1; i<=n; ++i)
{
u=i;
for (register int j=20; j>=0; --j)
if (p[u][j] && d[i]-d[p[p[u][j]][0]]<=L && dis[i]-dis[p[p[u][j]][0]]<=S) u=p[u][j];
len[i]=d[i]-d[u]+1;
}
dfs2(1);
printf("%lld\n",ans[1]);
return 0;
}