树上随机游走

给定一棵有根树,树的某个结点上有一个硬币,在某一时刻硬币会等概率地移动到邻接结点上,问硬币移动到邻接结点上的期望距离.

需要用到的定义

  • T=(V,E)T=(V,E): 所讨论的树
  • d(u)d(u): 结点 uu 的度数
  • w(u,v)w(u,v): 结点 uu 与结点 vv 之间的边的边权
  • pup_u: 结点 uu 的父结点
  • root\textit{root}: 树的根结点
  • sonu\textit{son}_u: 结点 uu 的子结点集合
  • siblingu\textit{sibling}_u: 结点 uu 的兄弟结点集合

向父结点走的期望距离

设 f(u)f(u) 代表 uu 结点走到其父结点 pup_u 的期望距离,则有:

f(u)=w(u,pu)+∑v∈sonu(w(u,v)+f(v)+f(u))d(u)f(u) = \cfrac{w(u,p_u) + \sum\limits_{v \in \textit{son}_u}(w(u,v) + f(v) + f(u))}{d(u)}

分子中的前半部分代表直接走向了父结点,后半部分代表先走向了子结点再由子结点走回来然后再向父结点走;分母 d(u)d(u) 代表从 uu 结点走向其任何邻接点的概率相同.

化简如下:

f(u)=w(u,pu)+∑v∈sonu(w(u,v)+f(v)+f(u))d(u)=w(u,pu)+∑v∈sonu(w(u,v)+f(v))+(d(u)−1)f(u)d(u)=w(u,pu)+∑v∈sonu(w(u,v)+f(v))=∑(u,t)∈Ew(u,t)+∑v∈sonuf(v)\begin{aligned} f(u) &= \cfrac{w(u,p_u) + \sum\limits_{v \in \textit{son}_u}(w(u,v) + f(v) + f(u))}{d(u)} \\ &= \cfrac{w(u,p_u) + \sum\limits_{v \in \textit{son}_u}(w(u,v) + f(v)) + (d(u)-1)f(u)}{d(u)} \\ &= w(u,p_u) + \sum\limits_{v \in \textit{son}_u}(w(u,v) + f(v)) \\ &= \sum\limits_{(u,t) \in E}w(u,t) + \sum\limits_{v \in \textit{son}_u}f(v) \end{aligned}

对于叶子结点 ll,初始状态为 f(l)=w(pl,l)f(l) = w(p_l, l).

当树上所有边的边权都为 11 时,上式可化为:

f(u)=d(u)+∑v∈sonuf(v)f(u) = d(u) + \sum\limits_{v \in \textit{son}_u}f(v)

即 uu 子树的所有结点的度数和,也即 uu 子树大小的两倍 −1-1(每个结点连向其父亲的边都有且只有一条,除 uu 与 pup_u 之间的边只有 11 点度数的贡献外,每条边会产生 22 点度数的贡献).

向子结点走的期望距离

设 g(u)g(u) 代表 pup_u 结点走到其子结点 uu 的期望距离,则有:

g(u)=w(pu,u)+(w(pu,ppu)+g(pu)+g(u))+∑s∈siblingu(w(pu,s)+f(s)+g(u))d(pu)g(u) = \cfrac{w(p_u,u) + \left(w(p_u,p_{p_u})+g(p_u)+g(u)\right) + \sum\limits_{s \in \textit{sibling}_u}(w(p_u,s)+f(s)+g(u))}{d(p_u)}

分子中的第一部分代表直接走向了子结点 uu,第二部分代表先走向了父结点再由父结点走回来然后再向 uu 结点走,第三部分代表先走向 uu 结点的兄弟结点再由其走回来然后再向 uu 结点走;分母 d(pu)d(p_u) 代表从 pup_u 结点走向其任何邻接点的概率相同.

化简如下:

g(u)=w(pu,u)+(w(pu,ppu)+g(pu)+g(u))+∑s∈siblingu(w(pu,s)+f(s)+g(u))d(pu)=w(pu,u)+w(pu,ppu)+g(pu)+∑s∈siblingu(w(pu,s)+f(s))+(d(pu)−1)g(u)d(pu)=w(pu,u)+w(pu,ppu)+g(pu)+∑s∈siblingu(w(pu,s)+f(s))=∑(pu,t)∈Ew(pu,t)+g(pu)+∑s∈siblinguf(s)=∑(pu,t)∈Ew(pu,t)+g(pu)+(f(pu)−∑(pu,t)∈Ew(pu,t)−f(u))=g(pu)+f(pu)−f(u)\begin{aligned} g(u) &= \cfrac{w(p_u,u) + \left(w(p_u,p_{p_u})+g(p_u)+g(u)\right) + \sum\limits_{s \in \textit{sibling}_u}(w(p_u,s)+f(s)+g(u))}{d(p_u)} \\ &= \cfrac{w(p_u,u) + w(p_u,p_{p_u}) + g(p_u) + \sum\limits_{s \in \textit{sibling}_u}\left(w(p_u,s)+f(s)\right)+(d(p_u)-1)g(u)}{d(p_u)} \\ &= w(p_u,u) + w(p_u,p_{p_u}) + g(p_u) + \sum\limits_{s \in \textit{sibling}_u}(w(p_u,s)+f(s)) \\ &= \sum\limits_{(p_u,t) \in E}w(p_u,t) + g(p_u) + \sum\limits_{s \in \textit{sibling}_u}f(s) \\ &= \sum\limits_{(p_u,t) \in E}w(p_u,t) + g(p_u) + \left(f(p_u)-\sum\limits_{(p_u,t) \in E}w(p_u,t)-f(u)\right) \\ &= g(p_u) + f(p_u) - f(u) \end{aligned}

初始状态为 g(root)=0g(\text{root}) = 0.

代码实现(以无权树为例)

vector<int> G[MAXN];

void dfs1(int u, int p) {
  f[u] = G[u].size();
  for (auto v : G[u]) {
    if (v == p) continue;
    dfs1(v, u);
    f[u] += f[v];
  }
}

void dfs2(int u, int p) {
  if (u != root) g[u] = g[p] + f[p] - f[u];
  for (auto v : G[u]) {
    if (v == p) continue;
    dfs2(v, u);
  }
}

本文内容来自 OI Wiki《树上随机游走》;作者与修订历史见原文。AIOJ 对排版、站内链接和资源路径做了格式适配。

内容依 CC BY-SA 4.0 与 SATA 许可共享;附加条款以原文声明为准。感谢 OI Wiki 作者与贡献者;请按 SATA 约定前往 OI Wiki 仓库 Star 支持。