1 条题解

  • 0
    @ 2025-8-24 22:55:43

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 览遍千秋
    将伤与泪汇成力化作拳

    搬运于2025-08-24 22:55:43,当前版本为作者最后更新于2024-03-05 15:16:30,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    本题解为官方题解。


    f[u]f[u] 为节点 uu 有水流时子树 uu 中有流水的节点数量的期望。

    f[u]=1+vsonup(u,v)f[v]f[u]=1+\sum_{v\in son_u} p_{(u,v)}f[v]

    g[u]g[u] 为节点 uu 的答案,则可以进行换根 DP 计算出 gg

    g[v]=f[v]+p(u,v)(g[u]p(u,v)f[v])g[v]=f[v]+p_{(u,v)}(g[u]-p_{(u,v)}f[v])

    总时间复杂度为 O(n+q)O(n+q)

    暴力

    2m2^m 枚举边的联通情况,计算出对应的概率和各个连通块大小累加答案,可以在 O((n+m)2m)O((n+m)2^m) 时间内预处理出所有点的答案,最终时间复杂度 O((n+m)2m+q)O((n+m)2^m+q)

    基环树

    f[u]f[u] 为环上的节点 uu 如果有水流下挂的子树中有水的期望节点数,这部分可以使用 Tree 部分的 DP 求得。

    令环上所有边的概率乘积为 PP,即 P=jCpjP=\prod_{j\in C} p_j,则 $g_i=\sum_{i,j\in C} (w(i,j)+\dfrac{P}{w(i,j)}-P)f_j$,其中 w(i,j)w(i,j) 为环上节点 i,ji,j 任意一个方向上之间的边的概率之积。

    对于该部分,断环成链后对边做前缀积,有 si=jipjs_i=\prod_{j\le i} p_j

    iji\geq ji<ji<j 分开讨论,得到 $g_i=s_i\sum_{j\le i}\dfrac{f_j}{s_j}+\dfrac{P}{s_i}\sum_{j\le i}f_js_j-P\sum_{j\le i}f_j+\dfrac{1}{s_i}\sum_{j>i}f_js_j+Ps_i\sum_{j>i}\dfrac{f_j}{s_j}-P\sum_{j>i}f_j$

    正序循环处理 jij\le i\sum,倒序循环处理 j>ij>i\sum。即可求出环上每个点的 gug_u,然后从环上向下做类似换根 DP 即可得到所有点的 gg

    由于求出 gg 的部分需要求出前缀积 sis_i 的逆元,时间复杂度为 O(nlogmod+m)O(n\log \operatorname{mod}+m)

    点仙人掌

    考虑这个图的 dfs 树,由于是点仙人掌,所以每个点只可能在一个简单环中,无向图的 dfs 树形如一棵树与若干条返祖边的组合,我们可以借鉴前述的 Tree 和 Pseudotree 两个部分的算法。

    首先选择一个节点作为 dfs 树的树根进行 dfs,对于每个节点计算 f[u]f[u],表示当该节点有水的时候在不走环边的情况下其 dfs 树子树中期望会有多少个节点有水,由于是点仙人掌,每个点、边均只会属于至多一个环。对于某个环的最顶部节点要特殊处理,环顶部节点的 f[u]f[u] 应该为 uu 到该 dfs 树子树中的期望联通点数。

    计算完成后可以得到根节点的 gg,然后类似换根 DP 往下做,对于节点 uu - 非环节点 vv,转移方式与树型的转移相同,当一个环的顶部节点得到 uu 之后就可以使用基环树的方法算出环上所有点的答案。

    于是成功的预处理了所有点的答案。


    标准解法

    对于非环中的节点,f[u]f[u] 代表若节点 uu 有水流,在其 dfs 树的子树中期望会有多少个点也会有水流,状态转移方程:

    g[u]=f[u]=vsonup(u,v)f[v]g[u]=f[u]=\sum_{v\in son_u} p_{(u,v)}f[v]

    对于环中的节点,则 f[u]f[u] 代表若节点 uu 有水流,在不经过环上的边的情况下其 dfs 树的子树中期望会有多少个点也会有水流,状态转移方程:

    $$g[u]=f[u]=\sum_{v\in son_u,(u,v)\notin C}p_{(u,v)}f[v] $$

    若该节点为环的顶部节点,则 f[u]f[u] 代表若节点 uu 有水流,在其 dfs 树的子树中期望会有多少个点也会有水流,此时对于这个环上只考虑子树内的节点的情况下,将其视为一个基环树,根据基环树部分分的计算方法重新计算出 f[u]f[u] ,有:

    $$f[u]=\sum_{v\in C} (w(u,v)+\dfrac{P}{w(u,v)}-P)f[v] $$P=(x,y)Cp(x,y)P=\prod_{(x,y)\in C} p_{(x,y)}

    综上可以计算出每个节点的 f[u]f[u]

    对于前述的计算每个节点的 f[u]f[u] 方法中,如果开始 dfs 的节点为 rootroot,那么 ans[root]=f[root]ans[root]=f[root],对于其余节点,我们将使用类似换根 DP 的方法自上而下计算 ans[u]ans[u]

    考虑从当前节点 uu 向 dfs 树上子节点 vv 进行推算。

    我们只考虑 u,vu,v 不在同一个环中的情况。

    容易发现此时 vv 一定是环的顶部节点,计算 ans[v]ans[v] 其实就是考虑 (u,v)(u,v) 这条边会给节点 vv 带来的改变,容易发现,f[v]f[v] 只考虑了 dfs 树中 vv 下方的部分,我们将 vvans[u]ans[u] 中去掉即可得到一个类似子树的部分的贡献,将其加到 f[v]f[v] 中即可得到 ans[v]ans[v],即:

    $$ans[v]=f[v]+p_{(u,v)}(ans[u]-f[v]\times p_{(u,v)}) $$

    同时,当一个环的顶部节点的 ans[]ans[] 确定之后,其实我们就可以算出环上每个点的 ans[]ans[],参考基环树部分,我们需要的就是得到环上每个节点下挂的一个子树对于环上的对应子树根节点的贡献,但是在 Part1 中我们因为无法确认环的顶部节点的这部分值不能立即确定,但是现在可以确定了,对于顶部节点,我们考虑其 dfs 树父亲的那条边带来的额外贡献后就可以算出这个环上的全部 ans[]ans[] 了,方法和基环树部分分一样。

    然后发现,当 u,vu,v 在同一个环中时,ans[]ans[] 一定都计算完毕了。

    综上计算出了每个点的 ans[]ans[],可以 O(1)O(1) 回答询问。

    总时间复杂度 O((n+m)logmod+Q)O((n+m)\log \text{mod}+Q)

    • 1

    [湖北省选模拟 2024] 玩具销售员 / tartaglia

    信息

    ID
    9654
    时间
    1500ms
    内存
    1024MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者