zoukankan      html  css  js  c++  java
  • 题解 P3412 【仓鼠找sugar II】

    (huge exttt{P3412})

    题意

    给定一棵树,求任意一条路径从起点随机游走到终点的期望距离的期望。

    思路

    讨论求出每条边的贡献,当且仅当每条路径两个端点分别在这条边分成两个连通块中。

    一些约定: (vin u) 表示 (v)(u) 的子节点,(sum[u]=sum_{vin u} up[v])(p[u]) 表示 (u) 的连边数量,(fa[u]) 表示 (u) 的父亲。

    对于每条边 (u o v) 它的两种期望:

    向上走的期望可以由 (u o fa[u]) 或者 (u o v o u o fa[u]) 得到。

    向下走的期望可以由 (u o v) 或者 (u o v' o u o v) 或者 (u o fa[u] o u o v) 得到((v'in u&v' e v))。

    然后发现这些都可以通过已知项求得,对其讨论即可。

    列式子求解每条边向上走向下走的期望步数,为了方便标记每条边,(up[u])(down[u]) 都表示连 (u) 的父边,而 (up) 表示向上,(down) 对应向下。

    则会有下面的式子(感觉我推烦了,但还是比较清晰的吧):

    [up[u]=frac{1}{p[u]}+frac{1}{p[u]}(sum_{vin u}(1+up[v]+up[u]))\ up[u]=frac{1}{p[u]}+frac{(p[u]-1)up[u]}{p[u]}+frac{1}{p[u]}(sum_{vin u}(1+up[v]))\ up[u]=1+p[u]-1+sum_{vin u}up[v]\ up[u]=p[u]+sum_{vin u}up[v] ]

    [down[u]=frac{1}{p[fa[u]]}+frac{1}{p[fa[u]]}(sum_{vin fa[u]&v e u}1+up[v]+down[u])+frac{1}{p[fa[u]]}(1+down[fa[u]]+down[u])\ donw[u]=1+frac{(p-1)(down[u])}{p[fa[u]]}+frac{1}{p[fa[u]]}(sum[fa[u]]-up[u]+down[fa[u]])\ down[u]=p[fa[u]]+sum[fa[u]]-up[u]+down[fa[u]] ]

    然后就很容易了。

    代码

    int a, b, up[N + 5], sum[N + 5], down[N + 5], ans, siz[N + 5];
    vector<int> st[N + 5];
    
    void dfs(int n, int fa) {
    	siz[n] = 1;
    	rep(i, 0, siz(st[n]) - 1) {
    		int v = st[n][i];
    		if (v == fa) continue;
    		dfs(v, n);
    		siz[n] += siz[v];
    		(sum[n] += up[v]) %= mod;
    	}
    	up[n] = (siz(st[n]) + sum[n]) % mod;
    }
    
    void Dfs(int n, int fa) {
    	if (n != 1) down[n] = (siz(st[fa]) + sum[fa] - up[n] + down[fa] + mod) % mod;
    	(ans += siz[n] * (a - siz[n]) % mod * (down[n] + up[n]) % mod) %= mod;
    	rep(i, 0, siz(st[n]) - 1) {
    		int v = st[n][i];
    		if (v == fa) continue;
    		Dfs(v, n);
    	}
    }
    
    int qpow(int n, int m = mod - 2) {
    	int res = 1;
    	for (; m; m >>= 1) {
    		if (m & 1) res = res * n % mod;
    		n = n * n % mod;
    	}
    	return res;
    }
    
    signed main() {
    	// freopen("in1.in", "r", stdin);
    	// freopen("out.out", "w", stdout);
    	a = read();
    	int x, y;
    	rep(i, 1, a - 1) {
    		x = read();
    		y = read();
    		st[x].PB(y);
    		st[y].PB(x);
    	}
    	dfs(1, 0);
    	Dfs(1, 0);
    	printf("%lld", ans * qpow(a * a % mod) % mod);
    	return 0;
    }
    
  • 相关阅读:
    原单,尾货的科普贴
    c code
    考试
    一个笔试题
    注意自己的聊天内容可能招致被拐卖儿童
    酷壳网陈皓:开发者实用学习资源汇总[转]
    性格测试
    最实用的心理调节技巧,让你的情感细胞提升一下吧!
    Makefile教程
    Extjs中的迭代
  • 原文地址:https://www.cnblogs.com/RedreamMer/p/14784021.html
Copyright © 2011-2022 走看看