工人的请愿书 UVa 12186(贪心)

题意:

一个老板和n个员工组成树状结构,每个员工都有自己的唯一上司,老板的编号为0,员工1~n,工人们打算签署一个志愿书给老板,但无法跨级,当一个中级员工(非是工人的员工)的直属下属中不小于T%的人签字时,他也会签字并且递给他的直属上司,问:要让老板收到请愿书至少需要多少个工人签字

思路:
贪心做
设d(u)表示让u给上级发信最少需要多少个工人。假设u有k个子节点,则至少需要c=(k*T-1)/100+1个直接下属发信才行。把所有子节点的d值从小到大排序,前c个加起来即可。最终答案是d(0)。

#include <bits/stdc++.h>
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
#define pll pair<ll,ll>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep1(i,a,b) for(int i=a;i>=b;i--)
#define rson rt<<1|1,m+1,r
#define lson rt<<1,l,m
using namespace std;
const int N=1e5+100;
vector<int>sons[N];//存放i的所有直属下属
int n, T;
int dp(int u)
{
    if (sons[u].empty())
        return 1;//工人
    int ksons[u].size();
    vector<int>d; //存放u的直属下属的工人数
    for (int i=0;i<k;i++)
        d.push_back(dp(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 (cin>>n>>T&&n&&T)
    {
        memset(sons,0,sizeof(sons));
        int x;
        rep(i,1,n)
        {
            cin>>x;
            sons[x].push_back(i);
        }
        int ans;
        ans=dp(0);
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ffgcc/article/details/80302675
今日推荐