Hdu 5866 Lucky E(树上点期望的最大值)

来源:互联网 发布:ppt幻灯片软件下载 编辑:程序博客网 时间:2024/06/03 22:42

传送门:Hdu 5866 Lucky E


题意:给你一棵树,有n个节点,m种操作,树上的每个点相当于一个士兵,有一个伤值,
m中操作,每种操作都有一个点的标号和一个概率,表示可以对这个点的子树造成1点伤害,
求受伤最高的士兵的伤值的期望


题解:摘自http://www.cnblogs.com/duoxiao/p/5784466.html

考虑到操作数M较小而树较大,所以可以对操作数进行计算。
假设初始时树上的节点的最大值为x,则在操作完成后的树上的节点的最大值不超过x+M,不低于x,所以可以枚举最终状态的值再计算概率。
设dp[i][k]表示操作i所作用的那棵子树v在操作完成后最大值不超过x+k的概率,maxtree(v) 为该子树初始时的最大值
那么可得递推式
dp[i][k]=p[i] ×× π(dp[j][k-1])+(1-p[i]) ×× π(dp[j][k-1]) j为i的同一棵子树上的后继操作( maxtree(v)<=maxtree(root)+k);
or dp[i][k]=0;(maxtree(v)>maxtree(root)+k);
注意到子树的最大值会比maxtree(root)小很多,因此k可能为负, 所以要加上偏移量M
为了便于计算,添加作用于根节点的概率为0的操作(root,0)
然后预处理出每个操作u的后继操作即可。
先给每一个树标记上dfs的入序indfn[v]和出序outdfn[v],那么作用在v节点上的操作的影响区间就是[indfn[v],outdfn[v]], 所以计算出区间之间的包含关系即可
最后结果为Σ(maxtree(root)+k) ×× (dp[0][k+MAX_M]-dp[0][k-1+MAX_M]);

#include<bits/stdc++.h>using namespace std;const int maxn=100100;typedef pair<int,double> P;const int MAX_Q=3011;vector<int>G[maxn],mp[maxn];double dp[MAX_Q][MAX_Q*2];int vis[maxn],root,st[maxn],ed[maxn],tot,maxv[maxn],n,m;P Q[maxn];bool cmp(P x,P y){    if(st[x.first]!=st[y.first])        return st[x.first]<st[y.first];    return ed[x.first]>ed[y.first];}void dfs(int u){    st[u]=++tot;    for(int i=0;i<G[u].size();i++){        int v=G[u][i];        dfs(v);        maxv[u]=max(maxv[u],maxv[v]);    }    ed[u]=tot;}int getnext(int u,int pre){    int v=Q[u].first;    if(~pre)    mp[pre].push_back(u);    for(int i=u+1 ; i<=m; i=getnext(i,u))  //计算出每个点的子树修改的范围        if(st[Q[i].first] > ed[v] )            return i;    return m+1;}double cal(int pre,int k){    int v=Q[pre].first;    if(dp[pre][k+MAX_Q]>-0.5)   return dp[pre][k+MAX_Q];    if(maxv[v] > maxv[root]+k)    return 0;    double ans1=Q[pre].second,ans2=1.0-Q[pre].second;    if(maxv[v]==maxv[root]+k)   ans1=0;    for(int i=0;i<mp[pre].size();i++){  //这个覆盖的查询的范围         ans1*=cal(mp[pre][i],k-1);         ans2*=cal(mp[pre][i],k);    }    dp[pre][k+MAX_Q]=ans1+ans2;    return dp[pre][k+MAX_Q];}int main(){    while(scanf("%d%d",&n,&m)!=EOF){        int u,v;        memset(dp,-1,sizeof(dp));        memset(vis,0,sizeof(vis));        for(int i=0;i<=n;i++)            mp[i].clear(),G[i].clear();        for(int i=1;i<n;i++)            scanf("%d%d",&u,&v),vis[u]=1,G[v].push_back(u);        for(int i=1;i<=n;i++){            scanf("%d",&maxv[i]);            if(vis[i]==0)   root=i;        }        tot=0;        dfs(root);        for(int i=1;i<=m;i++)             scanf("%d%lf",&Q[i].first,&Q[i].second);        Q[0]={root,0};        sort(Q+1,Q+m+1,cmp);        getnext(0,-1);        double ans=0;        for(int i=0;i<=m;i++)            ans+=1.0*(maxv[root]+i)*( cal(0,i) - cal(0,i-1)  );        printf("%.6f\n",ans);    }    return 0;}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 微信官方电话一直打不通怎么办 对方欠货款股东换了不还怎么办 闲鱼买的东西确认收货有问题怎么办 不让微信好友看到吃鸡的名字怎么办 金鹰贵宾积分卡过期了怎么办 小宝机器人一直停在联网界面怎么办 手机版的有道云笔记忘记邮箱怎么办 钡灌肠复查钡剂排空不良怎么办 两个月宝宝灌肠后不排便怎么办 一岁宝宝肠套叠灌肠后拉肚子怎么办 苹果手机自带的天气没有了怎么办? 衣服在洗衣机里忘记拿出来怎么办 苹果se手机系统占内存太大怎么办 客人把饭店老板打了民警怎么办 商场嫌品牌低端不让入驻怎么办 带着孩子坐飞机座位不在一起怎么办 公司老板跑路了员工该怎么办 超市买的衣服防盗扣忘记取了怎么办 在超市买的衣服那个扣没取怎么办啊 超市散称商品条码老记不住怎么办 app账号密码忘记了怎么办注销难 幼儿老师遇到家长比较孩子该怎么办 发的微信公众号内容重复了怎么办 招嫖诈骗微信转账被骗怎么办 朋友在深圳龙岗被传销骗了要怎么办 怀疑家里人被传销组织骗去了怎么办 怀疑家人被骗进传销了该怎么办 b本扣3分了怎么办2018 抖音里面就剩人头的视频怎么办 自学参加普通高考那小高考怎么办 如果小学生长胸只长了一个该怎么办 脸上毛多导致的毛孔粗怎么办 吃了激素药头发掉的厉害怎么办 剪发的剪子中间的螺丝扣总掉怎么办 染完头发后一段时间长新头发怎么办 睡觉头发老被老公压着怎么办 漆盖关节不自在怎么办?吃什么好 摆床头的位置后面是弧形位怎么办 君子兰的根全烂掉了只剩茎怎么办 老板不发工资怎么办 没签合同的 牙套粘在牙齿上的松了怎么办