开了很久的坑,显然对于每个节点,选择以它为根的最小的那几个最优,于是每个节点开一个大根堆,从叶子往上合并就好,如果不合法就弹掉最大的元素
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std; int n,m;
inline int read(){
register char ch = getchar();
while(!isdigit(ch)) ch = getchar();
int rtn = 0;
while(isdigit(ch)) rtn = rtn*10 + ch - '0' , ch = getchar();
return rtn;
}
//============================================================
struct Node{
Node *Son,*Brother;
int key,size;
Node(){}
Node(Node *Son,Node *Brother,int key,int size):Son(Son),Brother(Brother),key(key),size(size){}
}ttt[MAXN],*root[MAXN],*null;
int cnt_node;
inline Node * New_node(Node *s,Node *b,int k,int ss){
return &(ttt[++cnt_node] = Node(s,b,k,ss));
}
inline Node * merge(Node *a,Node *b){
if(a==null) return b;
if(b==null) return a;
if(a->key<b->key) swap(a,b);
a->Brother = 0;
b->Brother = a->Son;
a->Son = b;
a->size += b->size;
return a;
}
inline Node * pop(Node *a){
queue<Node *> q;
for(Node *now = a->Son;now!=null;now = now->Brother)
q.push(now);
while(q.size() > 1u){
Node *a = q.front(); q.pop();
Node *b = q.front(); q.pop();
q.push(merge(a,b));
}
return q.front();
}
//============================================================
struct t1{
int to,nxt;
}edge[MAXN<<1]; int cnt_edge;
int fst[MAXN];
void addedge(int x,int y){
edge[++cnt_edge].to = y;
edge[cnt_edge].nxt = fst[x];
fst[x] = cnt_edge;
}
int cst[MAXN],led[MAXN];
long long sum[MAXN];
long long ans = 0;
void dfs(int now){
sum[now] = cst[now];
root[now] = New_node(null,null,cst[now],1);
for(int tmp = fst[now];tmp;tmp=edge[tmp].nxt){
int aim = edge[tmp].to;
dfs(aim);
root[now] = merge(root[aim],root[now]);
sum[now] += sum[aim];
while(sum[now] > m){
sum[now] -= (root[now]->key);
root[now] = pop(root[now]);
}
}
ans = max(ans,(long long)led[now]*( root[now]->size ));
}
int main(){
freopen("1.in","r",stdin);
n = read(),m = read();
for(int i=1;i<=n;++i){
int f = read();
addedge(f,i);
cst[i] = read() , led[i] = read();
}
null = new Node(0,0,0,0);
dfs(0);
printf("%lld",ans);
return 0;
}