工人的请愿书 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;
}