【jzoj4765】【Crisis】【树形动态规划】

来源:互联网 发布:各国工资数据 编辑:程序博客网 时间:2024/06/03 04:40

题目大意

有一颗有根树,有至少t%的儿子向它提交申请,它就会提交申请。问最少多少个叶子提交申请,根才会提交申请。

解题思路

f[i]表示当前节点提交申请最少需要的叶子节点数,对儿子的f值排序后选最小的t%即可。

code

#include<set>#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>#define LF double#define LL long long#define max(a,b) ((a>b)?a:b)#define min(a,b) ((a>b)?b:a)#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)using namespace std;int const maxn=100000,inf=2147483647;int n,t,gra,to[maxn+10],next[maxn+10],begin[maxn+10],f[maxn+10],son[maxn+10],a[maxn+10];void insert(int u,int v){    to[++gra]=v;    next[gra]=begin[u];    begin[u]=gra;}void dfs(int now){    f[now]=(begin[now]==0);    for(int i=begin[now];i;i=next[i])        dfs(to[i]);    a[0]=0;    for(int i=begin[now];i;i=next[i])        a[++a[0]]=f[to[i]];    sort(a+1,a+a[0]+1);    fo(i,1,son[now])        f[now]+=a[i];}int main(){    freopen("d.in","r",stdin);    freopen("d.out","w",stdout);    scanf("%d%d",&n,&t);    fo(i,1,n){        int x;scanf("%d",&x);        insert(x,i);        son[x]++;    }    fo(i,0,n){        if(son[i]*t%100==0)son[i]=son[i]*t/100.0;        else son[i]=son[i]*t/100.0+1;    }    dfs(0);    printf("%d",f[0]);    return 0;}
0 0
原创粉丝点击