UVa 12186 工人的请愿书

详见紫书P444

题目

输入:
员工数n 百分比T
员工1的直属上司 员工2的直属上司 ... 员工n的直属上司

3 100
0 0 0
3 50
0 0 0
14 60
0 0 1 1 2 2 2 5 7 5 7 5 7 5
0 0

输出
需要签字的最少工人(叶子)数

3
2
5

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 100000+5;
int n, T;
vector<int> sons[maxn]; // sons[i]:结点i的子节点列表

void init()
{
    for(int i = 0; i<maxn; ++i) sons[i].clear();
    for(int i=1; i<=n; ++i)
    {
        int boss;
        scanf("%d", &boss);
        sons[boss].push_back(i);
    }
}

int solve(int u)
{
    if(sons[u].empty()) return 1;   // 让一个工人(叶子)签字,需要他自己签字
    int k = sons[u].size();
    vector<int> d;  // d[u]:让u给上级发信最少需要的工人数
    for(int i=0; i<k; ++i)
    {
        d.push_back(solve(sons[u][i]));
    }
    sort(d.begin(), d.end());
    int c = (k*T-1)/100 + 1;
    int ans = 0;
    for(int i=0; i<c; ++i) ans += d[i];
    return ans;
}

int main()
{
    while(scanf("%d%d", &n, &T)==2 && n)
    {
        init();
        printf("%d\n", solve(0));
    }
}
posted @ 2022-11-19 17:59  shimmer_ghq  阅读(26)  评论(0)    收藏  举报