#听说 Lucky_Glass 博客都要日更了#
(你等着,我马上就咕)
# 题意
有一个 $n$ 个点 $m$ 条边的有向图,节点编号为 $0$ 到 $n-1$,其中每条边 $u\to v$ ($u,v$ 是边的编号)满足 $0\le\left\lfloor\frac v4\right\rfloor-\left\lfloor\frac u4\right\rfloor\le1$,但是满足该条件的 $u,v$ 之间不一定有边。每条边 $u\to v$ 有权重 $w_{u\to v}$。
进行 $q$ 次询问,询问有以下类型:
- 给定 $x,y,k$:添加一条权重为 $k$ 的边 $x\to y$,$x,y$ 满足 $0\le\left\lfloor\frac y4\right\rfloor-\left\lfloor\frac x4\right\rfloor\le1$。(保证当前没有 $x\to y$ 这条边)
- 给定 $x,y$:删除边 $x\to y$。(保证当前存在 $x\to y$)
- 给定 $x,y$:从 $x$ 出发随机游走,到 $y$ 结束,求在 $y$ 结束的概率。其中随机游走的规则如下:若当前处于点 $u$,设 $u$ 的出边的权重之和为 $S_u$,则通过边 $u\to v$ 的概率为 $\frac{w_{u\to v}}{S_u}$。
(多组数据,不超过 $20$ 组)
数据规模:$1\le n\le50000$;$1\le m\le10^5$;$1\le q\le20000$。
# 解析
- 期望 & 动态规划
有一个比较常用的非常巧妙的转化:“求从点 $S$ 出发随机游走到点 $T$ 结束(到达后就停止移动)的概率”可以转化为“求从点 $S$ 出发随机游走到点 $T$ 结束,经过 $T$ 的期望 次数”。
正确性显然,因为最多只可能经过 $T$ 一次,那么期望就是“概率×值”,即 E(经过T的次数)=P(经过T零次)*0+P(经过T一次)*1=P(经过T一次)
。
先只考虑询问——可以设计 DP,$f_i$ 表示从 $x$ 出发到达 $y$ 期望经过 $i$ 多少次,转移方程式则为:
前面的求和式很好理解,关键是 $[i=x]$。因为计算期望需要考虑所有的贡献,对于起点 $x$ 来说,经过 $x$ 可能是从另外一个点经过边到达 $x$;也可能是随机游走一开始就在起点 $x$,有一个 $1$ 的贡献,也就是 $[i=x]$。
这也算是一个套路,现学现用~
但是非常不幸的是,这张图不一定是 DAG,就不得不用高斯消元 来转移。这样复杂度就变成了 $O(n^3)$,显然不能接受,考虑优化。
- 分块
正当这时(人群中突然冒出来一个光头!)(不是),我们发现题目中:“边 $u\to v$ 只存在于满足 $0\le\left\lfloor\frac v4\right\rfloor-\left\lfloor\frac u4\right\rfloor\le1$ 的 $u,v$ 之间”。
稍加思索,我们发现可以从 $0$ 开始每四个点分成一块。环只会出现在同一个块里,如果把一个块看成一个点,整张图就变成了若干链。
这样的话,就可以对每个块做高斯消元了!块大小为 $4$,所以高斯消元也只是 $4^3$ 的。
接下来就是考虑把每一块的结果合并起来得到答案了。
- 线段树
几乎是顺理成章,倒是很像另一道题。
一个 $n$ 行 $m$ 列($n$ 很小)的迷宫,每个位置要么是空地,要么是障碍。只能向右、上、下走。
- 询问从 $(u_x,u_y)$ 到 $(v_x,v_y)$ 的最少步数;
- 修改 $(x,y)$ 为空地/障碍。
给每个块编号,从左到右依次为 $0$ 到$\left\lceil\frac n4\right\rceil$。线段树维护区间 $[L,R]$:$d_{u,v}$ 表示从块 $L$ 的第 $u$ 个点出发,第一次到达 块 $R$ 时到达的点是 $R$ 的第 $v$ 个点的概率。
则考虑合并区间 $[L,M],[M+1,R]$,其实就是块 $M$ 和 $M+1$ 之间的转移 ——
- 给块 $M$ 和 $M+1$ 的点重编号为 $1$ 到 $8$;
- 枚举 $M$ 的点 $S$ 作为起点;
- 按照 $f_v=\sum p_{u\to v}f_u+[v=S]$ 的规则建矩阵,高斯消元;
- 枚举块 $L$ 的起点 $u$,块 $M+1$ 的中继点 $t$,块 $R$ 的终点 $v$:把路径 $u\to S\to t\to v$ 统计入
d[u][v]
中。
这样就维护了线段树。
同时,我们发现修改边的操作也非常的 easy 了,只要修改点 $x$ 的出边,更新点 $x$ 的出边的权重之和,然后再 $O(\log n\times4^3)$ 让线段树递归更新 $\lfloor\frac x4\rfloor$ 即可。
那么查询呢?查询并没有要求“第一次到达 $y$ 所在块到达的点为 $y$”,因此还要做一个 $y$ 的块内的转移,计算出从 $y$ 所在块内每一个点出发,到达 $y$ 的概率。方法还是一样的。
- 漏洞
在之前的叙述中,我们默认了高斯消元是有解的,但是它真的可能无解!比如下面这张图:
从 $0$ 出发,到达 $1$。按照我们的 DP 定义,则 $f_3=f_4=+\infty$(永远无法到达),而实际上 $f_3=f_4=0$ 才符合转移。
我们发现在高斯消元时,因为
消元时必然有一个方程被消成“没有未知数,常数项不为0”的样子,就无解了。当然也会导致算出的结果不对。其实解决方法很简单,因为方程的数量和未知数数量相等,如果有一个方程被消成没有未知数,就必然有一个未知数没有出现在方程中。
发现这种情况时,把方程改为“该未知数=0”即可。
# 源代码
1 | /*Lucky_Glass*/ |
The End
Thanks for reading!
不知道“我马上就咕”这句话会不会被咕掉 : )