[Apio2012]dispatching

Posted Mafia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Apio2012]dispatching相关的知识,希望对你有一定的参考价值。

[Apio2012]dispatching

题目

在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。在这个帮派里,有一名忍者被称之为 Master。除了 Master以外,每名忍者都有且仅有一个上级。为保密,同时增强忍者们的领导力,所有与他们工作相关的指令总是由上级发送给他的直接下属,而不允许通过其他的方式发送。现在你要招募一批忍者,并把它们派遣给顾客。你需要为每个被派遣的忍者 支付一定的薪水,同时使得支付的薪水总额不超过你的预算。另外,为了发送指令,你需要选择一名忍者作为管理者,要求这个管理者可以向所有被派遣的忍者 发送指令,在发送指令时,任何忍者(不管是否被派遣)都可以作为消息的传递 人。管理者自己可以被派遣,也可以不被派遣。当然,如果管理者没有被排遣,就不需要支付管理者的薪水。你的目标是在预算内使顾客的满意度最大。这里定义顾客的满意度为派遣的忍者总数乘以管理者的领导力水平,其中每个忍者的领导力水平也是一定的。写一个程序,给定每一个忍者 i的上级 Bi,薪水Ci,领导力L i,以及支付给忍者们的薪水总预算 M,输出在预算内满足上述要求时顾客满意度的最大值。

1  ≤N ≤ 100,000 忍者的个数;

1  ≤M ≤ 1,000,000,000 薪水总预算; 

0  ≤Bi < i  忍者的上级的编号

1  ≤Ci ≤ M   忍者的薪水;

1  ≤Li ≤ 1,000,000,000   忍者的领导力水平。

INPUT

从标准输入读入数据。

第一行包含两个整数 N M,其中 N表示忍者的个数,M表示薪水的总预算。

接下来 N行描述忍者们的上级、薪水以及领导力。其中的第 i 行包含三个整Bi , C i , L i分别表示第i个忍者的上级,薪水以及领导力Master满足B i = 0并且每一个忍者的老板的编号一定小于自己的编号

OUTPUT

输出一个数,表示在预算内顾客的满意度的最大值。

SAMPLE

INPUT

5 4
0 3 3
1 3 5
2 2 2
1 2 4
2 3 1

OUTPUT

6

解题报告

题面粘过来有毒qwq

我们考虑维护树上每个节点的权值和,并使得被选中的点最多,所以我们考虑对每个点维护一个大根堆,不断$pop$堆顶知道全堆得权值和小于限制即可

由于需要合并子树的堆,所以就变成了左偏树裸题了qwq

技术分享
 1 /**************************************************************
 2     Problem: 2809
 3     User: MAFIA
 4     Language: C++
 5     Result: Accepted
 6     Time:1444 ms
 7     Memory:9936 kb
 8 ****************************************************************/
 9  
10 #include <iostream>
11 #include <cstring>
12 #include <cstdio>
13 using namespace std;
14 #define int long long
15 inline int read(){
16     int sum(0);char ch(getchar());
17     for(;ch<0||ch>9;ch=getchar());
18     for(;ch>=0&&ch<=9;sum=sum*10+(ch^48),ch=getchar());
19     return sum;
20 }
21 #define get_dis(x) (x?x->dis:-1)
22 #define get_sum(x) (x?x->sum:0)
23 #define get_size(x) (x?x->size:0)
24 struct node{
25     node *lch,*rch;
26     int key,sum,dis,size;
27     node(int x=0):lch(NULL),rch(NULL),key(x),sum(x),dis(0),size(1){}
28     inline void pushup(){
29         if(get_dis(this->lch)<get_dis(this->rch))
30             swap(this->lch,this->rch);
31         this->dis=get_dis(this->rch)+1;
32         this->size=get_size(this->lch)+get_size(this->rch)+1;
33         this->sum=get_sum(this->lch)+get_sum(this->rch)+this->key;
34     }
35 }*heap[100005];
36 inline node* merge(node *&x,node *&y){
37     if(!x)return y;if(!y)return x;
38     if(x->key<y->key)swap(x,y);
39     x->rch=merge(x->rch,y);
40     x->pushup();
41     return x;
42 }
43 inline void insert(node *&x,int v){
44     node *tmp(new node(v));
45     x=merge(x,tmp);
46 }
47 inline node* pop(node *&x){
48     if(!x)return NULL;
49     return merge(x->lch,x->rch);
50 }
51 struct edge{
52     int e;
53     edge *n;
54 }*pre[100005];
55 inline void insert(int s,int e){
56     edge *tmp(new edge);
57     tmp->e=e;tmp->n=pre[s];pre[s]=tmp;
58 }
59 int n,m,root;
60 long long ans,l[100005];
61 inline void dfs(int u){
62     for(edge *i=pre[u];i;i=i->n){
63         int e(i->e);dfs(e);
64         heap[u]=merge(heap[u],heap[e]);
65     }
66     while(heap[u]&&heap[u]->sum>m)
67         heap[u]=pop(heap[u]);
68     ans=max(ans,1ll*get_size(heap[u])*l[u]);
69 }
70 signed main(){
71 //  freopen("dispatching.in","r",stdin);freopen("dispatching.out","w",stdout);
72     n=read(),m=read();
73     for(int i=1;i<=n;++i){
74         int x(read()),y(read()),z(read());
75         if(!x)root=i;
76         else insert(x,i);
77         insert(heap[i],y);l[i]=z;
78     }
79     dfs(root);printf("%lld",ans);
80 }
View Code

 

以上是关于[Apio2012]dispatching的主要内容,如果未能解决你的问题,请参考以下文章

[Apio2012]dispatching

bzoj2809: [Apio2012]dispatching

BZOJ2809 [Apio2012]dispatching

APIO2012BZOJ2809派遣dispatching

Bzoj2809 [Apio2012]dispatching

BZOJ2809APIO2012dispatching