Codeforces - 839C - Journey(图论 + 概率 + 搜索、*1500)
839C - Journey(⇔源地址)
tag
⇔图论、⇔概率、⇔搜索、⇔*1500
题意
在七大王国里有 \(n\) 个城市和 \(n-1\) 条道路,每条道路连接两个城市,并且通过这些道路我们可以从任何一个城市到达任何一个城市。
席恩和阿莎在第一个城市骑上马,他们要通过这些路开始一次旅行。但是有雾,所以他们看不见他们的马带他们去了哪里。当马抵达一个城市的时候(包括第一个城市),它会去跟当前这个城市相连的城市。但是这是一匹奇怪的马,它只去他们以前没有去过的城市。在每个城市,马以相同的概率移动去上述符合要求的城市,并且当没有这样的城市(可走)时,马就停下了。
每条路的长度都是 \(1\),旅行从城市 \(1\) 开始,问这次旅行的期望长度(旅行长度的期望值)是多少?你可以通过这个链接来阅读一些关于期望(平均)值的文字。
思路
错误思路
首先上来一看,显然的搜索题,我以为题目是要求解到到叶子节点平均经过的举例,所以直接一个 \(\tt dfs\) 求解深度加上一个 \(\tt topsort\) 提取叶子节点算平均值了,样例坑的离谱,跑起来完全没感觉到有问题,然后光荣的WA了。
正解
这是一道图论+概率 \(\tt DP\) 的题目,特此写博文记录一下。
我们知道,期望等于概率乘以值,这道题中:
- 概率即为到达这个点的概率:已知某个点 \(i\) ,到达其子节点 \(son_i\) 的概率即为 \(\dfrac{P(i)}{子节点数量}\) ;
- 值即为这个点的深度。
所以直接用一个 \(\tt dfs\) 来维护这两个东西即可,没有别的套路了。
AC代码
点击查看代码
namespace Geometry { //几何
using ld = long double;
const ld PI = acos(-1);
const ld EPS = 1e-7;
template <class T, class S> inline bool equal(T x, S y) {
return x - y < EPS && x - y > -EPS;
}
// cout << fixed << setprecision(12);
}
using namespace Geometry;
namespace G {
vector<int> ver[N];
int deg[N], d[N];
ld ans;
void add(int x, int y) {
ver[x].push_back(y);
++ deg[y];
}
void dfs(int x, int fa, ld p) {
int siz = 0;
for (auto y : ver[x]) {
if (y == fa) continue;
++ siz;
}
for (auto y : ver[x]) {
if (y == fa) continue;
d[y] = d[x] + 1;
dfs(y, x, p / siz);
}
if (siz == 0) ans += p * d[x];
}
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cout << fixed << setprecision(15);
int n; cin >> n;
for (int i = 1; i < n; ++ i) {
int x, y; cin >> x >> y;
G::add(x, y), G::add(y, x);
}
G::dfs(1, -1, 1);
cout << G::ans;
return 0;
}
错误次数:2
第一发思路如上,稀碎;第二发改进了一下 \(n=1\) 的情况。
文 / WIDA
- 成文
首发于WIDA个人博客,仅供学习讨论