Jzoj4765 Crisis
X公司有着严格的等级制度,除了公司所有者小H以外,其他人都有一个直属上司。没有下属的员工称为工人,其他人则称为领导者。
为了加薪,工人们都会向他们的上司提交请愿书。当然,每个领导者都希望自己的下属能够尽可能快乐的工作,所以当至少有T%的下属提交请愿书时,那么这个领导者就会向自己的上司提交请愿书。计算百分比时,领导者只会计算直属上司是他的下属,当然,他也只会提交一次请愿书。
为了加薪,工人们都会向他们的上司提交请愿书。当然,每个领导者都希望自己的下属能够尽可能快乐的工作,所以当至少有T%的下属提交请愿书时,那么这个领导者就会向自己的上司提交请愿书。计算百分比时,领导者只会计算直属上司是他的下属,当然,他也只会提交一次请愿书。
如果最会小H收到了超过T%的请愿书,那么他将为所有工人们加薪。现在给出公司的构架和T的数值,你需要计算至少有多少工人提交请愿书才能使得小H给工人加薪。
树形DP
我们设f[i]表示使i提交申请的代价,叶子结点的代价为1,size[i]为i的直接下属
那么f[i]=min{Σf[j] (j∈son[i] 且 Σsize[j] >= size[i]*T%)}
那么我们处理处每个子树的f,排序取前面最小的直到取到T%为止
#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> G[100010],s[100010];
int n,T;
int cal(int x){
if(G[x].size()==0) return 1;
for(int i=0,z=G[x].size();i<z;++i)
s[x].push_back(cal(G[x][i]));
sort(s[x].begin(),s[x].end());
int ans=0;
for(int i=0,z=s[x].size();i*100<z*T;++i) ans+=s[x][i];
return ans;
}
int main(){
scanf("%d%d",&n,&T);
for(int x,i=1;i<=n;++i){
scanf("%d",&x);
G[x].push_back(i);
}
printf("%d\n",cal(0));
}