Jzoj4765 Crisis

来源:互联网 发布:许嵩雅俗共赏知乎 编辑:程序博客网 时间:2024/06/06 17:57
X公司有着严格的等级制度,除了公司所有者小H以外,其他人都有一个直属上司。没有下属的员工称为工人,其他人则称为领导者。
为了加薪,工人们都会向他们的上司提交请愿书。当然,每个领导者都希望自己的下属能够尽可能快乐的工作,所以当至少有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));}

原创粉丝点击