Crisis 纪中 4765 树形dp

来源:互联网 发布:轩辕剑纹身进阶数据 编辑:程序博客网 时间:2024/06/06 05:13

Description

最近几年,一场新的金融危机爆发了,这场危机使得很多人陷入的经济问题的困境。一些X公司的员工试图通过要求加薪度过这一难关。
X公司有着严格的等级制度,除了公司所有者小H以外,其他人都有一个直属上司。没有下属的员工称为工人,其他人则称为领导者。
为了加薪,工人们都会向他们的上司提交请愿书。当然,每个领导者都希望自己的下属能够尽可能快乐的工作,所以当至少有T%的下属提交请愿书时,那么这个领导者就会向自己的上司提交请愿书。计算百分比时,领导者只会计算直属上司是他的下属,当然,他也只会提交一次请愿书。
如果最会小H收到了超过T%的请愿书,那么他将为所有工人们加薪。现在给出公司的构架和T的数值,你需要计算至少有多少工人提交请愿书才能使得小H给工人加薪。

Input

第一行N,T(1≤N≤100000,1≤T≤100)。N表示公司的总人数(不包括小H)。每个员工编号为1到N。小H编号为0 。
第二行有N数,第I个数表示编号的员工直属上司的编号。

Output

一个数,最小需求的工人数。

分析

树状 DP,基础状态是所有叶节点的代价都是 1,对于每个节点,把它的子节点按代价从小到大选择直到满足百分比,作为这个点的代价

代码

type  arr=record    x,y:longint;    next:longint;  end;  arry=array[0..100010] of longint;var  edge:array[1..200000] of arr;  ls:array[0..200000] of longint;  f:array[0..200000] of longint;  n,t:longint;  nm:longint;procedure add(x,y:longint);begin  nm:=nm+1;  edge[nm].x:=x;  edge[nm].y:=y;  edge[nm].next:=ls[x];  ls[x]:=nm;end;procedure init;var  i,j,k:longint;begin  readln(n,t);  for i:=1 to n do    begin      read(j);      add(j,i);    end;end;procedure qsort(var a:arry; l,r:longint);var  i,j,k:longint;  temp:longint;  mid:longint;begin  if l>=r then exit;  i:=l; j:=r;  mid:=a[(l+r) div 2];  repeat    while a[i]<mid do i:=i+1;    while a[j]>mid do j:=j-1;    if i<=j      then        begin          temp:=a[i]; a[i]:=a[j]; a[j]:=temp;          i:=i+1; j:=j-1;        end;  until i>j;  qsort(a,l,j);  qsort(a,i,r);end;procedure dfs(x:longint);var  i,j,k:longint;  a:arry;begin  fillchar(a,sizeof(a),0);  i:=ls[x];  if i=0 then    begin      f[x]:=1;      exit;    end;  k:=0;  while i<>0 do    begin      dfs(edge[i].y);      k:=k+1;      a[k]:=f[edge[i].y];      i:=edge[i].next;    end;  qsort(a,1,k);  if abs((k/100*t)-trunc(k/100*t))<0.00001    then k:=trunc(k/100*t)    else k:=trunc(k/100*t+1);  for i:=1 to k do    f[x]:=f[x]+a[i];end;begin  init;  dfs(0);  write(f[0]);end.
0 0
原创粉丝点击