hdu 4035 Maze 概率DP+树形DP

做法:其实题目中给的就是一棵有根树,一开始闹惨以为可能存在多个连通分量。

带环的,数据量又那么大,又看了大神的博客,慢慢神伤...

如果当前节点是叶子节点,

那么dp[x]=1-e[x]-k[x]+k[x]*dp[1]+sigma(p[i]*dp[fahter[i]]);

如果不是

dp[x]=1-e[x]-k[x]+k[x]*dp[1]+sigma(p[i]*father[i])+sigma(p[i]*son[i]);

由于叶子节点没有son,而且,某个节点中的,他的儿子的faher就是自己(废话了,,),那么,在由叶子向根的递推过程中

所以dp[x]=(a[x]*dp[father]+b[x]*dp[1]+c[x])/(1-sigma(son(a[x])));

 

做的时候#define居然能让我写错了,,,

#include<cstdio>
#include<cstring>
#include<cmath>
#define no_no 1e50
#define zero(x) fabs(x)<1e-9
const int LMT=100003;
struct line
{
    int u,v;
    int next;
}le[LMT<<1];
int next[LMT],all,du[LMT];
double x[LMT],y[LMT],z[LMT],e[LMT],k[LMT];
void init(void)
{
    memset(next,-1,sizeof(next));
    memset(x,0,sizeof(x));
    memset(y,0,sizeof(y));
    memset(z,0,sizeof(z));
    memset(du,0,sizeof(du));
    all=0;
}
void insert(int u,int v)
{
    le[all].u=u;
    le[all].v=v;
    le[all].next=next[u];
    next[u]=all++;
}
bool dfs(int u,int pre)
{
    int v,xx;
    double temy=0;
    z[u]+=1-e[u]-k[u];
    x[u]+=k[u];
    for(xx=next[u];xx!=-1;xx=le[xx].next)
        if(le[xx].v!=pre)
        {
            v=le[xx].v;
            if(!dfs(v,u)&&1-k[u]-e[u]>0)return 0;
            x[u]+=x[v]*(1-k[u]-e[u])/du[u];
            temy+=y[v]*(1-k[u]-e[u])/du[u];
            z[u]+=z[v]*(1-k[u]-e[u])/du[u];
        }
        if(pre!=-1)y[u]+=(1-k[u]-e[u])/du[u];
        if(zero((temy-1.0)))return 0;
            x[u]/=(1-temy);
            y[u]/=(1-temy);
            z[u]/=(1-temy);
        return 1;
}
int main(void)
{
    int T,I,i,u,v,n;
    scanf("%d",&T);
    for(I=1;I<=T;I++)
    {
        init();
        scanf("%d",&n);
        for(i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            insert(u,v);
            insert(v,u);
            du[u]++;du[v]++;
        }
        for(i=1;i<=n;i++)
        {
            scanf("%lf%lf",&k[i],&e[i]);
            e[i]/=100;
            k[i]/=100;
        }
        printf("Case %d: ",I);
        if(!dfs(1,-1)||zero((1.0-x[1])))
            printf("impossible");
        else
            printf("%.6lf",z[1]/(1-x[1]));
        printf("\n");
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值