hihoCoder 1117 : 战争年代(期望)

hihoCoder 1117 : 战争年代(期望)

题目大意

因为出题人的恶意,现在世界变成了一个战火纷飞,每天都有人死去的年代。无数国家诞生而又被毁灭,一片混乱。

你作为战争之神,决定预测一下这个世界未来的导向。这个世界很奇妙,它的结构是一个树形图。城市之间有边相连,组成一棵树,所有边的边权都是1。

每个城市都会有颜色,一个国家就是一个同色的树上的城市的联通块。

你发现,在第0世纪,会出现一个伟大的君主,他征服了所有城市,所以第0时刻所有城市都是颜色0。然后之后,在第i个世纪,就会出现一位征服者,他会从城市xi开始,征服所有与城市xi距离不超过d的城市,也就是给所有距离城市xi不超过d的城市染上颜色i。你无法精确地预测d的值,但你知道他是一个0到di之间的均匀分布的整数。

你想知道到第m世纪结束,世界上国家的数量的期望是多少?注意如果一个颜色i的国家被从中间分裂成了几个,根据国家的定义它其实就直接变成了好几个国家,毕竟这些国家也没法通信了嘛。

数据范围

\[1 \le n, m \le 2000 \]

解题思路

又是新的联通块计算方法

关于树的另几个个小技巧 \(n = m +1, 2 = \sum (2-deg_x)\)

这道题也有个小技巧

就是连通块个数 = 两端点颜色不同的边个数 - 1

因此考虑每条边对答案的贡献

设 f[x] 表示边 \((u, v)\) 异色的概率,从 V 点开始染且 \(dis[u][V] < dis[v][V]\),有

\[f[x] = f[x] * \frac {dis[u][V]}{d[i] + 1} + \frac 1{d[i] + 1} \]

代码

const int N = 2005;
int h[N], ne[N<<1], to[N<<1], tot;
inline void add(int x, int y) {
	ne[++tot] = h[x], to[h[x] = tot] = y;
}

int dep[N], pos[N], d[N], m, n;
void dfs(int x, int fa) {
	for (int i = h[x]; i; i = ne[i]) {
		int y = to[i]; if (y == fa) continue;
		dep[y] = dep[x] + 1, dfs(y, x);
	}
}

double inv[N];
int main() {
	read(n), read(m);
	for (int i = 1, x, y;i < n; i++)
		read(x), read(y), add(x, y), add(y, x);
	for (int i = 1;i <= m; i++)
		read(pos[i]), read(d[i]), inv[i] = 1.0 / (d[i] + 1); 
	double ans = 0; 
	for (int i = 2;i <= tot; i += 2) {
		int x = to[i], y = to[i - 1];
		dep[x] = dep[y] = 0;
		dfs(x, y), dfs(y, x);
		double tp = 0;
		for (int j = 1;j <= m; j++) {
			if (d[j] < dep[pos[j]]) continue; 
			tp = tp * dep[pos[j]] * inv[j] + inv[j];
		}
		ans += tp;
	}
	printf ("%.8lf\n", ans + 1);
	return 0;
}
posted @ 2020-07-13 21:29  Hs-black  阅读(166)  评论(0编辑  收藏  举报