#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
const int maxn = 4e5 + 10;
struct edge {
int to, nxt;
}node[maxn]; int head[maxn], n, fa[maxn], cnt = 0;
ll a[maxn], b[maxn], c[maxn];
inline void add(int u, int v) {
node[cnt].nxt = head[u];
node[cnt].to = v;
head[u] = cnt++;
}
void dfs(int u, int f) {
fa[u] = f;
for (int i = head[u]; ~i; i = node[i].nxt) {
int v = node[i].to;
if (v == f) continue;
dfs(v, u);
}
}
ll t[maxn]; int vis[maxn], st[maxn], top = 0;
pair<ll, int>wz[maxn];
inline ll check(ll T) {
for (int i = 1; i <= n; i++) {
//bi + x * ci, bi + (x + 1) * ci, ..., bi + T * ci
//(T - x + 1) * (T - X + 2) / 2 * ci + (T - x + 1) * bi >= ai
if (b[i] >= a[i]) { t[i] = n; continue; }
if (b[i] == 0 && c[i] == 0) { t[i] = n - a[i]; continue; }
auto can = [&](ll x) {
if (c[i] >= 0) {
//if (c[i] > 0 && (T + 1) * T / 2 - x * (x - 1) / 2 > (a[i] + c[i] - 1) / c[i]) return true;
return (__int128_t)((T + 1) * T / 2 - x * (x - 1) / 2) * c[i] + (T - x + 1) * b[i] >= a[i];
}
else {
//bi + u * ci < 1
//u * ci < 1 - bi
//u < (1 - bi) / ci
ll u = (1 - b[i]) / c[i];
if (b[i] + u * c[i] >= 1) ++u;
if (T <= u) return (__int128_t)((T + 1) * T / 2 - x * (x - 1) / 2) * c[i] + (T - x + 1) * b[i] >= a[i];
else return (__int128_t)(u - 1) * u / 2 * c[i] + (u - 1) * b[i] + (T - u + 1) >= a[i];
}
};
ll l = 0, r = n + 1, mid;
while (l < r) {
mid = l + r >> 1;
if (can(mid)) l = mid + 1;
else r = mid;
}
t[i] = l - 1;
}
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n; i++) {
if (t[i] == -1) return 0;
}
for (int i = 1; i <= n; i++) wz[i] = { t[i], i };
sort(wz + 1, wz + n + 1); int p = 0;
for (int i = 1; i <= n; i++) {
ll now = wz[i].first; int u = wz[i].second;
if (now >= n) { vis[u] = -1; continue; }
if (vis[u]) continue;
while (!vis[u] && u) st[++top] = u, u = fa[u];
for (int j = top; j >= 1; j--) vis[st[j]] = ++p; top = 0;
}
for (int i = 1; i <= n; i++) if (vis[i] > t[i]) return 0;
return 1;
}
int main() {
memset(head, -1, sizeof(head));
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%lld%lld%lld", &a[i], &b[i], &c[i]);
for (int i = 1; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
add(u, v); add(v, u);
}
dfs(1, 0);
ll l = 1, r = 1e9, mid;
while (l < r) {
mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
printf("%lld\n", l);
return 0;
}
大概思路就是二分出 ti 表示 i 最晚种树的时间,排序然后每次跳父结点种树模拟。