1 条题解

  • 0
    @ 2025-12-2 10:39:35

    题意概述

    有一棵 NN 个节点的树,每个节点 ii 有一个加油站的燃料量 AiA_i(货车到达该节点时可以补充最多 AiA_i 单位燃料)。
    货车从某个节点 uu 出发时,油箱初始为空,会先加满 AuA_u 燃料。
    每条边 (u,v)(u,v) 有长度 ww(即消耗 ww 燃料)。
    货车从节点 uu 能到达相邻节点 vv 的条件是:离开 uu 时的燃料量 w\ge w
    货车可以经过任意多个节点,到达每个节点时可以补充燃料(但补充量不超过 AiA_i,且油箱无限大)。
    问有多少个有序对 (u,v)(u,v) 满足:从 uu 出发,可以到达 vv


    问题分析

    对于固定起点 uu,我们需要知道它能到达哪些点 vv
    这相当于在树上做“燃料可达性”传播:

    • uu 出发,有初始燃料 AuA_u
    • 走到相邻节点 vv 需要消耗 ww,到达后补充 AvA_v 燃料(最多补充 AvA_v,但实际补充量不能超过油箱剩余容量?题目说“可以在加油站补充不超过加油站燃料分量的燃料”,且油箱无限大,所以总是能补充 AvA_v)。
    • 因此,到达 vv 后燃料量变为 max(0,到达前燃料w)+Av\max(0, \text{到达前燃料} - w) + A_v
      不对,因为如果到达前燃料足够,到达后剩余燃料是 到达前燃料w\text{到达前燃料} - w,然后再加 AvA_v
      如果到达前燃料不足 ww,则无法到达 vv
      所以条件:离开上一节点时的燃料 w\ge w

    因此,从 uu 出发的过程可以看作:当前在节点 xx,拥有燃料 ff,能走到相邻节点 yy 当且仅当 fwxyf \ge w_{xy},走到 yy 后燃料变为 fwxy+Ayf - w_{xy} + A_y


    转化模型

    这类似于在树上做“能量传播”或“前缀和”问题。
    设从 uuvv 的路径为 u=x0,x1,,xk=vu = x_0, x_1, \dots, x_k = v,边权 wiw_i 连接 xi1x_{i-1}xix_i
    出发时燃料 f0=Auf_0 = A_u
    能走到 x1x_1 的条件:f0w1f_0 \ge w_1,到达后燃料 f1=f0w1+Ax1f_1 = f_0 - w_1 + A_{x_1}
    能走到 x2x_2 的条件:f1w2f_1 \ge w_2,即 Auw1+Ax1w2A_u - w_1 + A_{x_1} \ge w_2,到达后燃料 f2=f1w2+Ax2f_2 = f_1 - w_2 + A_{x_2}
    依此类推。

    归纳:能到达 xtx_t 的条件是: [ A_u + \sum_{i=1}^{t} (A_{x_i} - w_i) \ge 0 \quad \text{且} \quad \text{对于所有 } 1 \le j \le t,\ A_u + \sum_{i=1}^{j-1} (A_{x_i} - w_i) \ge w_j ] 第二个条件等价于:路径上任意前缀的“净收益”足够支付下一段边的费用。


    进一步简化

    定义边权 ci=wic_i = w_i,节点权 ai=Aia_i = A_i
    uu 出发到达 vv 的路径上,设路径序列为 u=p0,p1,,pk=vu = p_0, p_1, \dots, p_k = v,边 (pi1,pi)(p_{i-1}, p_i) 权为 cic_i
    出发时燃料 F0=auF_0 = a_u
    到达 p1p_1 前需满足 F0c1F_0 \ge c_1,到达后 F1=F0c1+ap1F_1 = F_0 - c_1 + a_{p_1}
    能到 p2p_2F1c2F_1 \ge c_2,即 auc1+ap1c2a_u - c_1 + a_{p_1} \ge c_2

    更直观:令 bi=ai(从父亲到 i 的边权)b_i = a_i - \text{(从父亲到 i 的边权)}
    对于固定起点 uu,到达某节点 vv 的条件是:从 uuvv 的路径上,任意前缀的“累积燃料”不低于下一段边的需求。

    这类似于“路径最小值”问题:定义从 uuvv 路径上的一个函数:

    • 在起点 uu 处值为 aua_u
    • 经过边 (x,y)(x,y)ww 时,值减去 ww(消耗),然后加上 aya_y(补充)。

    于是到达节点 vv 的条件是:从 uuvv 路径上的最小前缀值(在每次加 aya_y 之前)必须 0\ge 0(实际上应该 \ge 下一条边的权,但这样不好统一)。


    另一种视角:转换为“差值”模型

    令每条边的新权值为 dxy=axwxyd_{xy} = a_x - w_{xy}
    含义:从 xx 出发到 yy,消耗 wxyw_{xy} 后,在 yy 补充 aya_y,所以从 xxyy 的净燃料变化是 wxy+ay-w_{xy} + a_y,但这不是从 xx 出发时的燃料,因为出发时还有 axa_x 补充?等等。

    更准确:设 SuS_u 表示从 uu 出发时的燃料量,出发时先加 aua_u,所以 Su=auS_u = a_u
    走到 vv(相邻)需要满足 SuwuvS_u \ge w_{uv},到达 vv 后剩余 SuwuvS_u - w_{uv},再加 ava_v,所以到达 vv 时的燃料量 Sv=Suwuv+avS_v = S_u - w_{uv} + a_v
    所以转移为 Sv=Su+(avwuv)S_v = S_u + (a_v - w_{uv}),前提是 SuwuvS_u \ge w_{uv}

    因此,如果把 avwuva_v - w_{uv} 看作边 (u,v)(u,v) 的“增益”,那么 Sv=Su+gain(u,v)S_v = S_u + \text{gain}(u,v),但前提是 SuwuvS_u \ge w_{uv}
    这个前提条件依赖于边的原始权值,不能完全吸收到增益里。


    关键观察

    对于树上的路径 uvu \to v,设路径为 u=x0,x1,,xk=vu=x_0, x_1, \dots, x_k=v
    定义 $P_j = \sum_{i=0}^{j} a_{x_i} - \sum_{i=1}^{j} w_{i}$,其中 wiw_i 是边 (xi1,xi)(x_{i-1}, x_i) 的权。
    那么到达 xjx_j 的条件是:对于所有 1tj1 \le t \le j,有 Pt1wtP_{t-1} \ge w_t

    等价于:对于路径上的任意位置 tt,有 au+i=1t1(axiwi)wta_u + \sum_{i=1}^{t-1} (a_{x_i} - w_i) \ge w_t

    这很难直接处理所有起点。


    经典技巧:点分治

    因为 N105N \le 10^5,我们需要 O(NlogN)O(N \log N) 或类似复杂度。
    点分治是处理树上路径统计问题的常用方法。

    对于分治中心 cc,考虑所有经过 cc 的路径 (u,v)(u,v)uuvv 在不同子树中)。
    我们需要统计满足条件的 (u,v)(u,v) 数量。

    对于从 cc 到某节点 xx 的路径(cc 作为起点),可以计算:

    • cc 出发到达 xx 所需的最小初始燃料量 needxneed_x(即保证从 ccxx 路径上不会燃料耗尽的最小初始值)。
    • 到达 xx 后剩余的燃料量 remxrem_x(如果从 cc 出发时有足够燃料的话)。

    类似地,如果 xx 是起点,cc 是途径点,也可以计算从 xxcc 的需求和剩余。


    计算 need 和 rem

    对于从 ccxx 的路径(cc 是起点): 设路径为 c=y0,y1,,yt=xc = y_0, y_1, \dots, y_t = x,边权 wiw_i(yi1,yi)(y_{i-1}, y_i)。 定义:

    • 初始燃料 F0=acF_0 = a_c(出发时补充)。
    • y1y_1F0w1F_0 \ge w_1,到达后 F1=F0w1+ay1F_1 = F_0 - w_1 + a_{y_1}
    • y2y_2F1w2F_1 \ge w_2,即 acw1+ay1w2a_c - w_1 + a_{y_1} \ge w_2

    可以递推计算 needxneed_x
    needxneed_x 是从 cc 出发到达 xx 所需的最小初始燃料量(即在 cc 出发时的燃料量必须至少为 needxneed_x 才能到达 xx)。
    递推:对于边 (p,q)(p, q)ww,从 ppqq,如果已知从 ccpp 所需的最小初始燃料 needpneed_p,以及到达 pp 后的剩余燃料 remprem_p(假设初始燃料正好为 needpneed_p),那么:

    • 要能到 qq,必须有 rempwrem_p \ge w
    • 如果 rempwrem_p \ge w,那么到达 qq 后剩余 remq=rempw+aqrem_q = rem_p - w + a_q,且 needq=needpneed_q = need_p(因为初始燃料已经够)。
    • 如果 remp<wrem_p < w,则需要增加初始燃料,使得 remp+Δwrem_p + \Delta \ge w,于是 needq=needp+(wremp)need_q = need_p + (w - rem_p),且 remq=aqrem_q = a_q(因为补足后到达 qq 时剩余 remp+Δw+aq=aqrem_p + \Delta - w + a_q = a_q)。

    这样可以在 O(路径长度)O(\text{路径长度}) 内计算。


    点分治步骤

    1. 选择重心 cc

    2. 对于 cc 的每个子树,计算子树内每个节点 xx(相对于 cc 作为起点)的 (needx,remx)(need_x, rem_x)

    3. 对于 cc 作为起点的情况,需要统计有多少对 (u,v)(u,v) 满足 uu 在某个子树,vv 在另一个子树,且从 uu 出发能到 vv 经过 cc
      这需要交换 uuvv 的角色,即从 uu 出发到 cc 需要满足一定条件,然后从 ccvv 也要满足条件。

    4. 具体地,对于有序对 (u,v)(u,v),路径 ucvu \to c \to v
      设从 uucc 的需求为 needucneed_{u\to c},剩余为 remucrem_{u\to c}
      设从 ccvv 的需求为 needcvneed_{c\to v},剩余为 remcvrem_{c\to v}
      条件:

      • uu 出发时燃料为 aua_u(因为出发时加满),所以必须 auneeduca_u \ge need_{u\to c},并且到达 cc 后燃料变为 remuc+(auneeduc)rem_{u\to c} + (a_u - need_{u\to c})(如果 au>needa_u > need,则多余部分保留)。
      • ccvv 需要初始燃料至少 needcvneed_{c\to v},而到达 cc 时的燃料为 remuc+(auneeduc)rem_{u\to c} + (a_u - need_{u\to c}),必须 needcv\ge need_{c\to v}

      所以条件为: [ a_u \ge need_{u\to c} \quad \text{且} \quad rem_{u\to c} + (a_u - need_{u\to c}) \ge need_{c\to v} ] 简化:$a_u + rem_{u\to c} - need_{u\to c} \ge need_{c\to v}$。

      定义 valu=au+remucneeducval_u = a_u + rem_{u\to c} - need_{u\to c},则条件为 auneeduca_u \ge need_{u\to c}valuneedcvval_u \ge need_{c\to v}

    5. 因此,对于每个子树,我们可以收集所有节点的 (needuc,valu)(need_{u\to c}, val_u),然后对于不同的子树,统计满足 valuneedvval_u \ge need_{v}(其中 needv=needcvneed_v = need_{c\to v})且 auneeduca_u \ge need_{u\to c}(这个条件对于 uu 自身是自动满足的,因为 needucneed_{u\to c} 是根据 aua_u 算出来的吗?需要检查)。

    实际上 needucneed_{u\to c} 的计算与 aua_u 有关,但 needucneed_{u\to c} 可能大于 aua_u 吗?可能,如果 uucc 路径上需求很大,aua_u 可能不够,那么 uu 根本到不了 cc,所以这样的 uu 不会出现在统计中。

    所以我们在计算 needucneed_{u\to c} 时,如果发现某一步需求大于 aua_u,则 uu 无法到达 cc,直接忽略。

    1. 因此,算法为:

      • 对每个子树,收集能到达 cc 的节点 uu,记录 valuval_u
      • 对于另一子树的节点 vv(从 cc 能到达 vv),记录 needv=needcvneed_v = need_{c\to v}
      • 统计有多少对 (u,v)(u,v) 满足 valuneedvval_u \ge need_v

      这可以用排序+双指针或树状数组完成。

    2. 还要考虑 u=cu = cv=cv = c 的情况,以及 uuvv 在同一个子树的情况(这些会在递归子问题时处理)。


    复杂度

    点分治 O(NlogN)O(N \log N),每次处理需要 O(mlogm)O(m \log m) 排序(mm 为子树大小),总复杂度 O(Nlog2N)O(N \log^2 N)


    总结

    本题是树上的路径可达性计数问题,通过点分治将路径分为两半,并利用 needneedremrem 的性质,将条件转化为值比较,从而用排序或树状数组统计。
    关键点:

    1. 将燃料约束转化为路径上的前缀条件。
    2. 使用点分治处理所有路径。
    3. 计算从一点到另一点的燃料需求和剩余量。
    4. 将条件简化为值比较,高效统计对数。

    • 1

    信息

    ID
    5739
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者