【数学期望】【LCA】【树形DP】树

题目大意

给你一棵有n个节点的树,以及m个询问,每个询问需要你回答一个点到另一个点要经过的期望边数

输入样例

4 2
1 2
2 3
3 4
1 4
3 4

输出样例

9
5 

数据范围

对于 20 % 20\% 20%的数据, N ⩽ 10. N \leqslant 10. N10.
对于 40 % 40\% 40%的数据, N ⩽ 1000. N \leqslant 1000. N1000.
另有 20 % 20\% 20%的数据, 保证给定的树是一条链.
对于 100 % 100\% 100%的数据, N ⩽ 100000 , Q ⩽ 100000. N \leqslant 100000, Q \leqslant 100000. N100000,Q100000.

解题思路

树上两点之间的距离要先求 l c a lca lca,然后可以通过前缀和来得出两点到 l c a lca lca距离
对于前缀和我们要先得出某个点到父亲节点和儿子节点的期望距离
我们设
d e g x deg_x degx为点 x x x的度数
d p 1 x dp1_x dp1x为点 x x x到父亲节点的期望距离
d p 2 x dp2_x dp2x为点 x x x的父亲节点到点x的期望距离
我们先算 d p 1 dp1 dp1
叶子结点到父亲节点的期望距离为1,因为只能往上
对于不是叶子结点的点 x x x
它直接到父亲节点的期望是 1 d e g x \frac{1}{deg_x} degx1 1 d e g x \frac{1}{deg_x} degx1的概率走这条边)
他到子节点i再回来再到父亲节点的期望是 1 + d p 1 i + d p 1 x d e g x \frac{1+dp1_i+dp1_x}{deg_x} degx1+dp1i+dp1x
所以可以得到以下式子

d p 1 x = 1 d e g x + ∑ i ∈ s o n x 1 + d p 1 i + d p 1 x d e g x dp1_x=\frac{1}{deg_x}+\sum_{i\in son_x}\frac{1+dp1_i+dp1_x}{deg_x} dp1x=degx1+isonxdegx1+dp1i+dp1x
化简式子
d p 1 x = 1 d e g x + d e g x − 1 d e g x + ( d e g x − 1 ) d p 1 x d e g x + ∑ i ∈ s o n x d p 1 i d e g x dp1_x=\frac{1}{deg_x}+\frac{deg_x-1}{deg_x} + \frac{(deg_x-1)dp1_x}{deg_x} + \sum_{i\in son_x}\frac{dp1_i}{deg_x} dp1x=degx1+degxdegx1+degx(degx1)dp1x+isonxdegxdp1i
移项
d p 1 x d e g x d e g x − ( d e g x − 1 ) d p 1 x d e g x = 1 d e g x + d e g x − 1 d e g x + ∑ i ∈ s o n x d p 1 i d e g x \frac{dp1_x deg_x}{deg_x}-\frac{(deg_x-1)dp1_x}{deg_x}=\frac{1}{deg_x}+\frac{deg_x-1}{deg_x} + \sum_{i\in son_x}\frac{dp1_i}{deg_x} degxdp1xdegxdegx(degx1)dp1x=degx1+degxdegx1+isonxdegxdp1i
化简
d p 1 x d e g x = 1 d e g x + d e g x − 1 d e g x + ∑ i ∈ s o n x d p 1 i d e g x \frac{dp1_x}{deg_x}=\frac{1}{deg_x}+\frac{deg_x-1}{deg_x} + \sum_{i\in son_x}\frac{dp1_i}{deg_x} degxdp1x=degx1+degxdegx1+isonxdegxdp1i
同乘 d e g x deg_x degx
d p 1 x = d e g x + ∑ i ∈ s o n x d p 1 i dp1_x=deg_x+ \sum_{i\in son_x}dp1_i dp1x=degx+isonxdp1i
求出dp1后我们来求dp2
父亲节点直接到目标子节点的期望是 1 d e g f a \frac{1}{deg_{fa}} degfa1
父亲节点先到父亲节点的父亲节点然后回来再到目标子节点的期望是 1 + d p 2 f a + d p 2 x d e g f a \frac{1+dp2_{fa}+dp2_x}{deg_{fa}} degfa1+dp2fa+dp2x
父亲节点先到其他子节点再回来再到目标子节点的期望是 1 + d p 1 i + d p 2 x d e g f a \frac{1+dp1_i+dp2_x}{deg_{fa}} degfa1+dp1i+dp2x
所以我们得到式子
d p 2 x = 1 d e g f a + 1 + d p 2 f a + d p 2 x d e g f a + ∑ i ∈ s o n f a ∣ i ≠ x 1 + d p 1 i + d p 2 x d e g f a dp2_x=\frac{1}{deg_{fa}} + \frac{1+dp2_{fa}+dp2_x}{deg_{fa}}+\sum_{i\in son_{fa}|i\neq x}\frac{1+dp1_i+dp2_x}{deg_{fa}} dp2x=degfa1+degfa1+dp2fa+dp2x+isonfai=xdegfa1+dp1i+dp2x
化简式子
d p 2 x = 1 d e g f a + 1 + d p 2 f a d e g f a + d p 2 x d e g f a + d e g f a − 2 d e g f a + ( d e g f a − 2 ) d p 2 x d e g f a + ∑ i ∈ s o n f a ∣ i ≠ x d p 1 i d e g f a dp2_x=\frac{1}{deg_{fa}} + \frac{1+dp2_{fa}}{deg_{fa}} + \frac{dp2_x}{deg{fa}}+\frac{deg_{fa}-2}{deg_{fa}}+\frac{(deg_{fa}-2)dp2_x}{deg_{fa}}+\sum_{i\in son_{fa}|i\neq x}\frac{dp1_i}{deg_{fa}} dp2x=degfa1+degfa1+dp2fa+degfadp2x+degfadegfa2+degfa(degfa2)dp2x+isonfai=xdegfadp1i
移项
d p 2 x d e g f a d e g f a − d p 2 x d e g f a − ( d e g f a − 2 ) d p 2 x d e g f a = 1 d e g f a + 1 + d p 2 f a d e g f a + d e g f a − 2 d e g f a + ∑ i ∈ s o n f a ∣ i ≠ x d p 1 i d e g f a \frac{dp2_x deg_{fa}}{deg{fa}} - \frac{dp2_x}{deg{fa}} - \frac{(deg_{fa}-2)dp2_x}{deg_{fa}}=\frac{1}{deg_{fa}} + \frac{1+dp2_{fa}}{deg_{fa}} +\frac{deg_{fa}-2}{deg_{fa}}+\sum_{i\in son_{fa}|i\neq x}\frac{dp1_i}{deg_{fa}} degfadp2xdegfadegfadp2xdegfa(degfa2)dp2x=degfa1+degfa1+dp2fa+degfadegfa2+isonfai=xdegfadp1i
合并
d p 2 x d e g f a = 1 d e g f a + 1 + d p 2 f a d e g f a + d e g f a − 2 d e g f a + ∑ i ∈ s o n f a ∣ i ≠ x d p 1 i d e g f a \frac{dp2_x}{deg{fa}}=\frac{1}{deg_{fa}} + \frac{1+dp2_{fa}}{deg_{fa}} +\frac{deg_{fa}-2}{deg_{fa}}+\sum_{i\in son_{fa}|i\neq x}\frac{dp1_i}{deg_{fa}} degfadp2x=degfa1+degfa1+dp2fa+degfadegfa2+isonfai=xdegfadp1i
同乘 d e g f a deg_{fa} degfa
d p 2 x = d p 2 f a + d e g f a + ∑ i ∈ s o n f a ∣ i ≠ x d p 1 i dp2_x=dp2_{fa} +deg_{fa}+\sum_{i\in son_{fa}|i\neq x}dp1_i dp2x=dp2fa+degfa+isonfai=xdp1i
根据 d p 1 x dp1_x dp1x的式子化简该式子
∵ d e g f a + ∑ i ∈ s o n f a ∣ i ≠ x d p 1 i = d e g f a + ∑ i ∈ s o n f a d p 1 i − d p 1 x = d p 1 f a − d p 1 x ∴ d p 2 x = d p 2 f a + d p 1 f a − d p 1 x \begin{aligned} \because deg_{fa}+\sum_{i\in son_{fa}|i\neq x}dp1_i & =deg_{fa}+\sum_{i\in son_{fa}}dp1_i-dp1_x \\ & =dp1_{fa}-dp1_x\end{aligned} \\ \therefore dp2_x=dp2_{fa} +dp1_{fa}-dp1_x degfa+isonfai=xdp1i=degfa+isonfadp1idp1x=dp1fadp1xdp2x=dp2fa+dp1fadp1x
然后求前缀和,再求 l c a lca lca
然后求 a a a l c a lca lca再到 b b b的期望步数即可

#include
#include
#include
#include
#define ll long long
#define wyc 1000000007
using namespace std;
ll n, m, x, y, z, g, tot, dep[110010], deg[110010], dp1[110010], dp2[110010], head[110010], f[110010][20];
struct rec
{
	ll to, next;
}a[210020];
void add(ll x, ll y)
{
	a[++tot].to = y;
	a[tot].next = head[x];
	head[x] = tot;
	return;
}
void dfs1(ll x, ll fa)//记录dp1
{
	f[x][0] = fa;//记录父亲
	dep[x] = dep[fa] + 1;//求深度
	dp1[x] = deg[x];
	for (int i = head[x]; i; i = a[i].next)
		if (a[i].to != fa)
		{
			dfs1(a[i].to, x);
			dp1[x] = (dp1[x] + dp1[a[i].to]) % wyc;
		}
	return;
}
void dfs2(ll x, ll fa)//求dp2
{
	for (int i = head[x]; i; i = a[i].next)
		if (a[i].to != fa)
		{
			dp2[a[i].to] = (dp1[x] - dp1[a[i].to] + dp2[x]) % wyc;
			dfs2(a[i].to, x);
		}
	return;
}
void dfs3(ll x, ll fa)//前缀和
{
	for (int i = head[x]; i; i = a[i].next)
		if (a[i].to != fa)
		{
			dp1[a[i].to] = (dp1[a[i].to] + dp1[x]) % wyc;
			dp2[a[i].to] = (dp2[a[i].to] + dp2[x]) % wyc;
			dfs3(a[i].to, x);
		} 
	return;
}
ll lca(ll x, ll y)
{
	if (dep[x] < dep[y]) g = x, x = y, y = g;
	for (int i = 16; i >= 0; --i)
		if (dep[x] - (1<<i) >= dep[y]) x = f[x][i];
	for (int i = 16; i >= 0; --i)
		if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
	return x == y?x:f[x][0];
}
int main()
{
	scanf("%lld%lld", &n, &m);
	for (int i = 1;i < n; ++i)
	{
		scanf("%lld%lld", &x, &y);
		deg[x]++;
		deg[y]++;
		add(x, y);
		add(y, x);
	}
	dfs1(1, 1);
	dfs2(1, 1);
	dfs3(1, 1); 
	for (int j = 1; j <= 16; ++j)
		for (int i = 1; i <= n; ++i)
			f[i][j] = f[f[i][j - 1]][j - 1];
	for (int i = 1; i <= m; ++i)
	{
		scanf("%lld%lld", &x, &y);
		z = lca(x, y);
		printf("%lld\n", ((wyc + dp1[x] - dp1[z]) % wyc + (wyc + dp2[y] - dp2[z]) % wyc) % wyc);
	}
	return 0;
}

你可能感兴趣的:(#,树形DP,图论,数学&数论,数学期望,LCA,树形DP,图论)