(纪中)4765. Crisis【DP】

66 篇文章 1 订阅

在这里插入图片描述
在这里插入图片描述


解题思路

比赛时原本以为只能拿部分分,没想到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]);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值