1. 程式人生 > >BZOJ2809: [Apio2012]dispatching

BZOJ2809: [Apio2012]dispatching

names submit getch ati 速度 add def led printf

[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 行包含三個整 B
i , 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