解题思路
比赛时原本以为只能拿部分分,没想到A了。
思路和之前做过的一题很像,从点0开始搜向他的儿子搜,计算出每个节点能向自己的上司提交请愿书至少需要几个人,设人数为
d
p
[
i
]
dp[i]
dp[i]。
具体做法就是把每次每个节点的儿子的
d
p
[
i
]
dp[i]
dp[i]排序,取前(儿子总数*T%)个,得出自己的
d
p
[
i
]
dp[i]
dp[i]
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#define ll long long
#define ldb long double
using namespace std;
int n,t,k,fa[100010],du[100010],dp[100010],head[100010];
struct c{
int x,next;
}a[100010];
void add(int x,int y)
{
a[++k].x=y;
a[k].next=head[x];
head[x]=k;
}
void work(int x){
priority_queue<int, vector<int>, greater<int> > p;
bool ok=0;
ldb w=du[x]*t*1.0/100*1.0;
for(int i=head[x];i;i=a[i].next)
{
ok=1;
int y=a[i].x;
work(y);
p.push(dp[y]);
}
if(ok)
du[x]=ceil(w);
else{
dp[x]=1;
return;
}
while(du[x])
{
du[x]--;
dp[x]+=p.top();
p.pop();
}
}
int main(){
scanf("%d%d",&n,&t);
for(int i=1;i<=n;i++)
{
scanf("%d",&fa[i]);
add(fa[i],i);
du[fa[i]]++;
}
work(0);
printf("%d",dp[0]);
}