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));
    }
}

 

posted @ 2017-08-23 06:43  Echo宝贝儿  阅读(134)  评论(0编辑  收藏  举报