HDU 4035 Maze(树形概率DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4035

题意:一棵树,从结点1出发,在每个结点 i 都有3种可能:(1)回到结点1 , 概率 Ki;(2)结束,概率 Ei;(3)随机走一条边。(Ki+Ei+随机走=1) 求到结束需要走的边数的期望。

思路:设Q[i]表示从i到结束的期望,设Q[i]=A[i]*Q[1]+B[i]*Q[fa[i]]+C[i]。

对于叶子节点,Q[i]=K[i]*Q[1]+E[i]*0+(1-K[i]-E[i])*(Q[fa[i]]+1),

对于叶子节点那么我们可得到:A[i]=K[i],B[i]=1-K[i]-E[i],C[i]=1-K[i]-E[i]。

对于非叶子节点,设与其相连的点有m个,则到每个点的概率都是temp=(1-K[i]-E[i])/m,Q[i]=K[i]*Q[1]+E[i]*0+temp*(Q[fa[i]]+Q[son[1]]+Q[son[2]+……Q[son[m-1]]]+1)。

计算出其子节点带入得到:令X=1-temp*sum(B[son[i]]),

A[i]=(K[i]+temp*sum(A[son[i]]))/X

B[i]=(1-K[i]-E[i])/m/X

C[i]=(1-K[i]-E[i]+temp*sum(C[son[i]]))/X

那么无解有两种情况:(1)中间计算过程出现X=0;(2)Q[1]=A[1]*Q[1]+B[1]+C[1],A[1]=1。





double A[N],B[N],C[N],K[N],E[N];

vector<int> g[N];

int n;



int flag;



void DFS(int u,int pre)

{

    A[u]=K[u];

    B[u]=(1-K[u]-E[u])/SZ(g[u]);

    C[u]=1-K[u]-E[u];

    int i,v;

    double temp=(1-K[u]-E[u])/SZ(g[u]),x=1;

    FOR0(i,SZ(g[u]))

    {

        v=g[u][i];

        if(v==pre) continue;

        DFS(v,u);

        A[u]+=temp*A[v];

        x-=temp*B[v];

        C[u]+=temp*C[v];

    }

    if(fabs(x)<EPS) flag=1;

    else A[u]/=x,B[u]/=x,C[u]/=x;

}





int main()

{

    int num=0;

    rush()

    {

        RD(n);

        int i,u,v;

        FOR1(i,n) g[i].clear();

        FOR1(i,n-1)

        {

            RD(u,v);

            g[u].pb(v);

            g[v].pb(u);

        }

        FOR1(i,n) RD(K[i],E[i]),K[i]/=100,E[i]/=100;

        flag=0;

        DFS(1,-1);

        printf("Case %d: ",++num);

        if(fabs(A[1]-1)<EPS||flag) puts("impossible");

        else PR(C[1]/(1-A[1]));

    }

    return 0;

}

  

你可能感兴趣的:(HDU)