2021.8.13提高B组模拟5T2 Crisis(小根堆)
Posted SSL_LKJ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021.8.13提高B组模拟5T2 Crisis(小根堆)相关的知识,希望对你有一定的参考价值。
Crisis
题目大意
最近几年,一场新的金融危机爆发了,这场危机使得很多人陷入的经济问题的困境。一些X公司的员工试图通过要求加薪度过这一难关。
X公司有着严格的等级制度,除了公司所有者小H以外,其他人都有一个直属上司。没有下属的员工称为工人,其他人则称为领导者。
为了加薪,工人们都会向他们的上司提交请愿书。当然,每个领导者都希望自己的下属能够尽可能快乐的工作,所以当至少有T%的下属提交请愿书时,那么这个领导者就会向自己的上司提交请愿书。计算百分比时,领导者只会计算直属上司是他的下属,当然,他也只会提交一次请愿书。
如果最会小H收到了超过T%的请愿书,那么他将为所有工人们加薪。现在给出公司的构架和T的数值,你需要计算至少有多少工人提交请愿书才能使得小H给工人加薪。
输入样例
第一行N,T(1≤N≤100000,1≤T≤100)。N表示公司的总人数(不包括小H)。每个员工编号为1到N。小H编号为0 。
第二行有N数,第I个数表示编号的员工直属上司的编号。
1.
3 100
0 0 0
2.
3 50
0 0 0
3.
14 60
0 0 1 1 2 2 2 5 7 5 7 5 7 5
输出样例
一个数,最小需求的工人数。
1.
3
2.
2
3.
5
1≤N≤100000,1≤T≤100
解题思路
我们可以先求出:
**每个节点需要多少个子节点(直系儿子)**才能向上递交请愿书
例如第三个样例(括号为所最少需要的节点数):
0
(
2
)
0(2)
0(2)
1
(
2
)
2
(
2
)
1(2)2~~(2)
1(2)2 (2)
3
(
0
)
4
(
0
)
5
(
3
)
6
(
0
)
7
(
2
)
3(0)4 ~~(0)5~~(3)6~~(0)7(2)
3(0)4 (0)5 (3)6 (0)7(2)
8
(
0
)
10
(
0
)
12
(
0
)
14
(
0
)
9
(
0
)
11
(
0
)
13
(
0
)
8(0)10(0)12(0)14(0)9(0)11(0)13(0)
8(0)10(0)12(0)14(0)9(0)11(0)13(0)
再跑一遍bfs/dfs(求出它的bfs/dfs序)
从最底端开始遍历节点
如果当前节点有儿子,则在堆中取出前k个数,累加起来,再放入父节点的小根堆中
(k为当前节点最少所需要的节点数)
否则,就直接将 1 1 1放入父节点的小根堆中(因为只有工人是没有儿子的)
AC代码
#include<cstdio>
#include<queue>
using namespace std;
int n,T,t,tot,head,tail;
int f[100005],p[100005],hd[100005],fa[100005],son[100005],need[100005],needson[100005];
struct node
{
int to,next;
}a[100005];
struct work
{
int x;
bool operator<(const work&a)const
{
return x>a.x;
}
};
void add(int x,int y)
{
a[++tot]=(node){y,hd[x]};
hd[x]=tot;
}
void bfs()//求bfs序
{
p[++tail]=0;
f[++t]=0;
while(head<tail)
{
int x=p[++head];
for(int i=hd[x];i;i=a[i].next)
{
p[++tail]=a[i].to;
f[++t]=a[i].to;
}
}
}
priority_queue<work>q[100005];
int main()
{
scanf("%d%d",&n,&T);
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
add(x,i);
son[x]++;
fa[i]=x;//x的父亲为i
}
for(int i=0;i<=n;i++)//求出每个节点需要的儿子
if(son[i]==0)need[i]=1;
else
{
if(son[i]*T%100==0)needson[i]=son[i]*T/100;
else needson[i]=int(son[i]*T/100)+1;
}
bfs();
for(int i=t;i>=1;i--)//遍历每个节点
{
int x=f[i];
if(son[x]!=0)
{
int o=0;
while(o<needson[x])
{
o++;
work xx=q[x].top();
need[x]+=xx.x;
q[x].pop();
}
}
q[fa[x]].push((work){need[x]});
}
printf("%d",need[0]);
return 0;
}
谢谢
以上是关于2021.8.13提高B组模拟5T2 Crisis(小根堆)的主要内容,如果未能解决你的问题,请参考以下文章
2021.8.13提高B组模拟5T1 Brothers(暴力)