首页 > 代码库 > BZOJ2809: [Apio2012]dispatching

BZOJ2809: [Apio2012]dispatching

[Submit][Status][Discuss]

Description

在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。在这个帮派里,有一名忍者被称之为 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并且每一个忍者的老板的编号一定小于自己的编号 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

思路{

  左偏树懂了,然而通过这道题还是可以发现并不熟练。

  首先是很容易想到采用树形DP的方法向上合并解。

  故想到使用可并堆。但是是大根堆还是小根堆?

  若小根堆(我最开始写的),应当顺序统计,直到和大于m为止,其他全部pop

  看出,这样的复杂度比较高。(然而我没有TLEWA了。。。。。。。。)

  大根堆的话,弹出元素直到元素和<=m.比较容易实现。

  在DFS的过程中,为了防止变量之间的冲突,

  还要设一个数组表示当前点所属的堆。(可能我就WA在这里吧。。。。)

  为了在COGS上速度超过PZ,我竟然使用了读入优化。。。。。。

  技术分享

}

 

#include<bits/stdc++.h>
#define RG register
#define il inline 
#define N 100010
#define LL long long
using namespace std;
int v[N],l[N],r[N],d[N],L[N],n,head[N],tot,BL[N],sz[N];LL sum[N];
struct ed{int nxt,to;}e[N];int m;LL ans;
void add(RG int u,RG int v){e[tot].nxt=head[u];e[tot].to=v;head[u]=tot++;}
il int merge(RG int x,RG int y){
  if(!x||!y)return x+y;
  if(v[x]<v[y])swap(x,y);
  r[x]=merge(r[x],y);
  if(d[r[x]]>d[l[x]])swap(r[x],l[x]);
  d[x]=d[r[x]]+1;return x;
}
il int getint(){
    int w=0;bool q=0;
    char c=getchar();
    while((c>‘9‘||c<‘0‘)&&c!=‘-‘) c=getchar();
    if(c==‘-‘) c=getchar(),q=1;
    while(c>=‘0‘&&c<=‘9‘) w=w*10+c-‘0‘,c=getchar();
    return q?-w:w;
}
il void dfs(int u){BL[u]=u;sum[u]=v[u];sz[u]=1;
  for(RG int i=head[u];i!=-1;i=e[i].nxt){
      RG int v=e[i].to;
      dfs(v);sum[u]+=sum[v];
      sz[u]+=sz[v];
      BL[u]=merge(BL[u],BL[v]);
  }while(sum[u]>m&&sz[u]){
    sum[u]-=v[BL[u]];
    BL[u]=merge(r[BL[u]],l[BL[u]]);
    sz[u]--;
  }ans=max(ans,(LL)sz[u]*L[u]);
}
int main(){
  freopen("dispatching.in","r",stdin);
  freopen("dispatching.out","w",stdout);
  memset(head,-1,sizeof(head));
  n=getint(),m=getint();
  for(RG int i=1;i<=n;++i){int ytk;
    ytk=getint(),v[i]=getint(),L[i]=getint();
    add(ytk,i);
  }dfs(1);printf("%lld",ans);
  return 0;
}

 

  

 

 
 
 

BZOJ2809: [Apio2012]dispatching