[题解]HDU4035 Maze

题目描述

一棵\(n\)个节点的树,从1号结点开始游戏,在每一个点\(x\)

  • \(a[x]/100\)的可能掉进陷阱死翘翘回到1重新开始
  • \(b[x]/100\)的可能找到出口并结束游戏
  • 剩下的可能中,你等概率随机选一条和它相连的边(可以是父亲)走过去

问期望多少步结束游戏

\(1\leq T \leq 30,1\leq n \leq 10000\)

分析

\(dp[x]\)表示位于\(x\)节点时,期望走几步才能结束游戏

那么\(dp[x]=0.01a[x]*dp[1]+0.01b[x]*0+0.01(1-a[x]-b[x])*(\frac{1}{cnt}(\sum dp[son]+dp[1]+1))\)

看了一下数据范围发现并不能承受高斯消元的时间复杂度

我们发现,每一个点的\(dp\)值之和父亲、1号点还有儿子有关,那么叶子节点的\(dp\)值可以用父亲和1号点表示,这样往上代,合并同类项之后可以发现,每一个点的值都可以表示为:

\(dp[x]=...*dp[1]+...*dp[fa[x]]+...\)(常数项)

所以只需要维护一下每一项的系数就可以\(O(n)\)求解了,记得特判Impossible

代码

void SEARCH(int x,int pa){
    f[x][0]=f[x][1]=f[x][2]=0;
    int cnt=0;
    for(int r=lst[x];r;r=nxt[r]){
        cnt++;
        if(edge[r]==pa)continue;
        SEARCH(edge[r],x);
    }
    DB lef=(100-a[x]-b[x])*0.01;
    DB hlp=0;
    for(int r=lst[x];r;r=nxt[r]){
        if(edge[r]==pa)continue;
        int pos=edge[r];
        f[x][0]+=f[pos][0];
        f[x][2]+=f[pos][2];
        hlp+=f[pos][1];
    }
    f[x][0]=(lef*f[x][0])/(1.0*cnt)+a[x]*0.01;
    f[x][2]=(lef*f[x][2])/(1.0*cnt)+lef;
    if(x==1)f[x][1]=0;else f[x][1]=lef/(1.0*cnt);
    hlp=hlp*lef/(1.0*cnt);
    hlp=1.0-hlp;
    if(x==1)hlp-=f[x][0];
    if(hlp<=0)f[x][0]=f[x][1]=f[x][2]=0;
    else rep(i,0,2)f[x][i]/=hlp;
}

猜你喜欢

转载自www.cnblogs.com/SCL123/p/11831202.html