HDU4035 Maze 题解

题目链接

分析:

f u f_u fu表示在点 u u u时期望需要经过多少条边才能逃出,记 s o n u son_u sonu为点 u u u的儿子的集合, f a u fa_u fau u u u的父亲, d u d_u du为点 u u u的度,那么显然有:
f u = k u f 1 + ( 1 − k u − e u ) ( ( ∑ v   ∈   s o n u f v + f f a u ) / d u + 1 ) (1) \tag1 f_u = k_uf_1 + (1 - k_u - e_u)((\sum_{v \,\in\, son_u}f_v + f_{fa_u}) / d_u + 1) fu=kuf1+(1kueu)((vsonufv+ffau)/du+1)(1)
经典套路,设:
f u = a u f 1 + b u f f a u + c u (2) \tag2 f_u = a_uf_1 + b_uf_{fa_u} + c_u fu=auf1+buffau+cu(2)
将 ( 2 ) 将(2) (2)式带入 ( 1 ) (1) (1)式,得:
f u = k u f 1 + ( 1 − k u − e u ) ( ∑ v   ∈   s o n u ( a v f 1 + b v f u + c v ) + f f a u ) / d u + ( 1 − k u − e u ) f_u = k_uf_1 + (1 - k_u - e_u)(\sum_{v\,\in\, son_u}(a_vf_1 + b_vf_u + c_v) + f_{fa_u}) / d_u + (1 - k_u - e_u) fu=kuf1+(1kueu)(vsonu(avf1+bvfu+cv)+ffau)/du+(1kueu)
t = ( 1 − k u − e u ) / d u , S a = ∑ v   ∈   s o n u a v t = (1 - k_u - e_u) / d_u,Sa = \sum_{v\,\in\,son_u}a_v t=(1kueu)/du,Sa=vsonuav S b , S c Sb,Sc Sb,Sc以此类推,整理一下,得:
f u = ( k u + t S a ) f 1 + t f f a u + t S c + t d u 1 − t S b f_u = \frac{(k_u + tSa)f_1 + tf_{fa_u} + tSc + td_u}{1 - tSb} fu=1tSb(ku+tSa)f1+tffau+tSc+tdu
即:
a u = k u + t S a 1 − t S b , b u = t 1 − t S b , c u = t S c + t d u 1 − t S b a_u = \frac{k_u + tSa}{1 - tSb},b_u = \frac{t}{1 - tSb},c_u = \frac{tSc + t d_u}{1 - tSb} au=1tSbku+tSabu=1tSbtcu=1tSbtSc+tdu
特别地,对于叶子节点,有 S a = S b = S c = 0 , d u = 1 Sa = Sb = Sc = 0,d_u = 1 Sa=Sb=Sc=0,du=1。带入式子显然有:
t = 1 − k u − e u , a u = k u , b u = 1 − k u − e u , c u = 1 − k u − e u t = 1 - k_u - e_u,\quad a_u = k_u,\quad b_u = 1 - k_u - e _u,\quad c_u = 1 - k _u - e _u t=1kueu,au=ku,bu=1kueu,cu=1kueu
递归处理一遍即可。求出 a 1 , b 1 , c 1 a_1,b_1,c_1 a1,b1,c1后,有 f 1 = a 1 f 1 + ( b 1 × 0 ) + c 1 f_1 = a_1f_1 + (b_1 \times 0) + c_1 f1=a1f1+(b1×0)+c1,即答案为 f 1 = c 1 1 − a 1 f_1 = \frac{c_1}{1 - a_1} f1=1a1c1

注意分母为 0 0 0时输出impossible.

Code:

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int maxn = 1e4 + 50;
const double eps = 1e-9;
int T,n,x,y,cnt,last[maxn],d[maxn];
double a[maxn],b[maxn],c[maxn],k[maxn],e[maxn];
struct Edge{
    int v,nxt;
}_e[2 * maxn];
int read(){
    int x = 0;
    char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
    return x;
}
inline void insert(int x,int y){
    cnt ++,_e[cnt].v = y,_e[cnt].nxt = last[x],last[x] = cnt;
}
bool dfs(int u,int fa){
    if(d[u] == 1 && u != 1){//叶子节点,直接赋值
        a[u] = k[u],b[u] = 1 - k[u] - e[u],c[u] = 1 - k[u] - e[u];
        return 1;
    }
    double Sa = 0,Sb = 0,Sc = 0;
    for(int i = last[u]; i; i = _e[i].nxt){
        int v = _e[i].v;
        if(v == fa) continue;
        if(!dfs(v,u)) return 0;
        Sa += a[v],Sb += b[v],Sc += c[v];
    }
    double t = (1 - k[u] - e[u]) / d[u];
    if(fabs(1 - t * Sb) < eps) return 0;//分母为零,无解
    a[u] = (k[u] + t * Sa) / (1 - t * Sb);
    b[u] = t / (1 - t * Sb);
    c[u] = (t * Sc + t * d[u]) / (1 - t * Sb);
    return 1;
}
int main(){
    T = read();
    for(int i = 1; i <= T; i ++){
        n = read(),cnt = 0;
        for(int i = 1; i <= n; i ++) d[i] = 0,last[i] = 0;
        for(int i = 1; i < n; i ++){
            x = read(),y = read(),d[x] ++,d[y] ++;
            insert(x,y),insert(y,x);
        }
        for(int i = 1; i <= n; i ++) k[i] = read() / 100.0,e[i] = read() / 100.0;
        if(dfs(1,0) && fabs(1 - a[1]) >= eps) printf("Case %d: %f\n",i,c[1] / (1 - a[1]));//有解
        else printf("Case %d: impossible\n",i);
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值