uva12186 Another Crisis
题目大意:
世界危机发生了,工人们请求加薪。一个老板和n个员工组成树状结构,每个员工都有自己的唯一上司,Boss的编号为0,员工1~n,工人们打算签署一个志愿书给老板,但无法跨级,当一个中级员工(非是工人的员工)的直属下属中不小于T%的人签字时,他也会签字并且递给他的直属上司,问:要让Boss收到请愿书至少需要多少个工人签字
/* 设d[u]表示让u给上级发信至少需要多少个工人。假设u有k个子节点,则至少需要C=(kT-1)100+1的直接下属发信才行。把所有的子节点的d值从小到大排序,前C个加起来即可。时间复杂度:O(nlogn) */ #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define maxn 100010 int n,t,num,head[maxn]; struct node{ int to,pre; }e[maxn]; void Insert(int from,int to){ e[++num].to=to; e[num].pre=head[from]; head[from]=num; } int dfs(int now){ int tmp[maxn],cnt=0,res=0; bool flag=0;//判断是否是叶子节点 for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; tmp[++cnt]=dfs(to); flag=1; } if(!flag)return 1; sort(tmp+1,tmp+cnt+1); int limit=(cnt*t-1)/100+1; for(int i=1;i<=limit;i++)res+=tmp[i]; return res; } int main(){ //freopen("Cola.txt","r",stdin); while(1){ scanf("%d%d",&n,&t); memset(e,0,sizeof(e)); memset(head,0,sizeof(head)); num=0; if(n==0&&t==0)return 0; int x; for(int i=1;i<=n;i++){ scanf("%d",&x); Insert(x,i); } printf("%d\n",dfs(0)); } }