zoukankan      html  css  js  c++  java
  • [APIO 2012]派遣

    Description

    在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。

    在这个帮派里,有一名忍者被称之为Master。除了Master以外,每名忍者都有且仅有一个上级。为保密,同时增强忍者们的领导力,所有与他们工作相关的指令总是由上级发送给他的直接下属,而不允许通过其他的方式发送。

    现在你要招募一批忍者,并把它们派遣给顾客。你需要为每个被派遣的忍者支付一定的薪水,同时使得支付的薪水总额不超过你的预算。另外,为了发送指令,你需要选择一名忍者作为管理者,要求这个管理者可以向所有被派遣的忍者发送指令,在发送指令时,任何忍者(不管是否被派遣)都可以作为消息的传递人。管理者自己可以被派遣,也可以不被派遣。当然,如果管理者没有被排遣,你就不需要支付管理者的薪水。

    你的目标是在预算内使顾客的满意度最大。这里定义顾客的满意度为派遣的忍者总数乘以管理者的领导力水平,其中每个忍者的领导力水平也是一定的。

    写一个程序,给定每一个忍者i的上级Bi,薪水Ci,领导力Li,以及支付给忍者们的薪水总预算M,输出在预算内满足上述要求时顾客满意度的最大值。

    Input

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

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

    Output

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

    Sample Input

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

    Sample Output

    6

    Hint

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

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

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

    1 ≤ Ci ≤ M 忍者的薪水;

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

    对于 30%的数据,N ≤ 3000。

    题解

    有用平衡树做的,这里给出可并堆的写法。

    首先我们由贪心的思想我们可以知道:对于每个点,我们把每个以他为代表的子树里的所有点,从小到大排好序。然后一直选小的,直到不满足条件为止。

    我们从叶子到根进行合并即可。用按$DFS$逆序操作。

    我们将以其为根的子树放在一个按照花销为关键词的大根堆里面,一直$pop$掉堆顶,直到整个堆里面的花费$<=n$

    再将这个堆中剩余的元素并到其父亲所在的堆中,继续操作。

    最后统计一下答案即可。

     1 #include<set>
     2 #include<map>
     3 #include<cmath>
     4 #include<ctime>
     5 #include<queue>
     6 #include<stack>
     7 #include<vector>
     8 #include<cstdio>
     9 #include<string>
    10 #include<cstdlib>
    11 #include<cstring>
    12 #include<iostream>
    13 #include<algorithm>
    14 #define LL long long
    15 #define RE register
    16 #define IL inline
    17 using namespace std;
    18 const LL N=100000;
    19 const LL INF=~0u>>1;
    20 
    21 IL LL Max(const LL &a,const LL &b) {return a>b ? a:b;}
    22 
    23 struct node
    24 {
    25     LL key,cost,dist;
    26     node *l,*r;
    27     LL ldist() {return l ? l->dist:0;}
    28     LL rdist() {return r ? r->dist:0;}
    29 }H[N+5],*root[N+5];
    30 LL father[N+5],sum[N+5],remain[N+5];
    31 node* Merge(node* a,node* b);
    32 
    33 LL n,m;
    34 LL b,c,l;
    35 
    36 struct tt
    37 {
    38     LL to,next;
    39 }edge[N+5];
    40 LL path[N+5],top;
    41 IL void Add(LL u,LL v);
    42 LL Rank[N+5],tail;
    43 void Dfs(LL r,LL father);
    44 
    45 int main()
    46 {
    47     scanf("%lld%lld",&n,&m);
    48     for (RE LL i=1;i<=n;i++)
    49     {
    50         scanf("%lld%lld%lld",&b,&c,&l);
    51         father[i]=b;
    52         remain[i]=1;
    53         sum[i]=H[i].cost=c;
    54         H[i].key=l;
    55         root[i]=H+i;
    56         Add(b,i);
    57     }
    58     Dfs(0,0);
    59     for (RE LL i=0;i<n;i++)
    60     {
    61         LL u=Rank[i];
    62         while (sum[u]>m)
    63         {
    64             sum[u]-=root[u]->cost;
    65             remain[u]--;
    66             root[u]=Merge(root[u]->l,root[u]->r);
    67         }
    68         sum[father[u]]+=sum[u];
    69         remain[father[u]]+=remain[u];
    70         root[father[u]]=Merge(root[father[u]],root[u]);
    71     }
    72     LL ans=-INF;
    73     for (RE LL i=0;i<=n;i++) ans=Max(ans,H[i].key*remain[i]);
    74     printf("%lld
    ",ans);
    75     return 0;
    76 }
    77 
    78 IL void Add(LL u,LL v)
    79 {
    80     edge[++top].to=v;
    81     edge[top].next=path[u];
    82     path[u]=top;
    83 }
    84 void Dfs(LL r,LL father)
    85 {
    86     for (RE LL i=path[r];i;i=edge[i].next) if (edge[i].to!=father) Dfs(edge[i].to,r);
    87     Rank[tail++]=r;
    88 }
    89 node* Merge(node* a,node* b)
    90 {
    91     if (!a||!b) return a ? a:b;
    92     if (a->cost<b->cost) swap(a,b);
    93     a->r=Merge(a->r,b);
    94     if (a->ldist()<a->rdist()) swap(a->l,a->r);
    95     a->dist=a->rdist()+1;
    96     return a;
    97 }
  • 相关阅读:
    Sereja and Bottles-水题有点坑爹
    what we benefit from big data
    SwipeRefreshLayout与ViewPager滑动事件冲突解决
    java连接数据库核心代码
    spring mvc中实现csrf安全防御简记
    一题多解(八)—— 矩阵上三角(下三角)的访问
    面向对象举例(一) —— 顶点(vertex)、边(edge)与图(graph)
    面向对象举例(一) —— 顶点(vertex)、边(edge)与图(graph)
    Python 辨异 —— __init__ 与 __new__
    Python 辨异 —— __init__ 与 __new__
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7396492.html
Copyright © 2011-2022 走看看