题意:
给你一棵树(也可能是森林)
站在每个节点时
1)有ki的几率回到节点1
2)有ei的几率离开
3)随机移动到一个相邻的节点
最开始在1,求离开需要移动的次数的期望。
思路:
一开始打算直接上方程然后求解线性方程组来着。。
后来发现判断无解难以处理(1e5的数据。。)
1)方程很容易写出来,注意我们是在树上进行dp,所以最好区分father和children
2)边界是叶子节点
3)在dp过程中和最和求解时都要判断无解
==>更详细的题解
const double EPS = 1e-10;
int n;
double A[Maxn+1], B[Maxn+1], C[Maxn+1], k[Maxn+1], e[Maxn+1];
vector<int> g[Maxn+1];
int dfs(int now, int fa) {
int sz = g[now].size();
double p0 = (1 - k[now] - e[now])/sz, k0 = 0, k1 = 0, k2 = 0;
if (fa == -1)
{A[now] = k[now];B[now] = 0;C[now] = 0;}
else
{A[now] = k[now];B[now] = p0;C[now] = p0;}
// 遍历所有child
rep(i, 0, sz-1)
if (g[now][i] != fa) {
int j = g[now][i];
if (dfs(j, now) == -1) return -1;
k0 += B[j];
k1 += A[j];
k2 += (C[j] + 1);
}
k0 = 1.0 - p0*k0;A[now] += p0*k1;C[now] += p0*k2;
if (abs(k0) < EPS) return -1;
A[now] /= k0;B[now] /= k0;C[now] /= k0;
return 1;
}
void solve(int num) {
if (dfs(1, -1) == -1 || abs(1.0- A[1]) < EPS) {
printf("Case %d: impossible\n", num);
return;
}
printf("Case %d: %.6f\n", num, C[1]/(1-A[1]));
}