- 其实就是对每个子树找到最多能派遣的人数乘这个子树根的领导力。 但是n和m的范围不能跑树上背包。
- 对每个子树维护一个堆,把所有节点的佣金扔到大根堆里面。sum大于m就把堆顶pop掉。堆的size就是最多的人数。
- 关键是几棵子树怎么合并,直接启发式合并,就是这样。
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
typedef __int128_t li;
//#define int long long
#define PII pair<int, int>
const int N = 1e5 + 5;
const int M = 1e2 + 5;
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const double PI = acos(-1.0);
int n, m;
ll c[N], l[N], id[N];
ll sum[N], ans = 0;
int h[N], e[N << 1], ne[N << 1], idx;
priority_queue<ll, vector<ll>, less<ll> > q[N];
void add( int a, int b ) {
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void merge(int v, int u) {
if(q[id[v]].size() > q[id[u]].size()) swap(id[v], id[u]), swap(sum[v], sum[u]);
while(q[id[v]].size())
q[id[u]].push(q[id[v]].top()), sum[u] += q[id[v]].top(), q[id[v]].pop();
}
void dfs( int u ) {
if(c[u] < m) sum[u] += c[u], q[id[u]].push(c[u]);
for ( int i = h[u]; ~i; i = ne[i] ) {
int v = e[i];
dfs(v);
merge(v, u);
}
while (sum[u] > m){
sum[u] -= q[id[u]].top(), q[id[u]].pop();
}
ans = max(ans, l[u] * (ll)q[id[u]].size());
}
int main () {
memset(h, -1, sizeof h);
cin >> n >> m;
for ( int i = 1; i <= n; ++ i ) {
int bi; cin >> bi >> c[i] >> l[i];
add(bi, i);
}
for ( int i = 1; i <= n; ++ i ) id[i] = i;
dfs(1);
cout << ans << endl;
return 0;
}