zoukankan      html  css  js  c++  java
  • [BZOJ2878][NOI2012]迷失游乐园(环套树DP+概率)

    推荐讲解:https://www.cnblogs.com/Tunix/p/4561493.html

    首先考虑树的情况,就是经典的树上概率DP。先DP出down表示从这个点向儿子走能走的期望长度,再DP出up表示向父亲走的期望长度,注意算up的时候要注意消除原先此点对父亲的down的影响。

    再考虑环的情况,由于环上点不超过20个,所以怎么暴力DP都好,算出up后down用同样的方法DP即可。

    概率递推式比较多,主要考虑好各种点的情况(树根,非树根,环上点,环外点,叶子)。

    再注意下式子里如果某项分母为0则忽略这项。

    剩下的就是心态稳健地调试了。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     6 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
     7 typedef long long ll;
     8 using namespace std;
     9 
    10 const int N=200010;
    11 bool d[N];
    12 int n,m,cnt,tim,tot,u,v,w,a[N],b[N],fa[N],pre[N],cf[N],dfn[N];
    13 int son[N],h[N],nxt[N<<1],to[N<<1],val[N<<1];
    14 double ans,dn[N],up[N];
    15 void add(int u,int v,int w){ to[++cnt]=v; val[cnt]=w; nxt[cnt]=h[u]; h[u]=cnt; }
    16 int F(int x){ return x-1+((x==1)?tot:0); }
    17 
    18 void Dn(int x,int fa){
    19     dn[x]=0;
    20     For(i,x) if ((k=to[i])!=fa && !d[k])
    21         son[x]++,Dn(k,x),dn[x]+=dn[k]+val[i];
    22     if (son[x]) dn[x]/=son[x];
    23 }
    24 
    25 void Up(int x,int c){
    26     up[x]=c;
    27     if (son[fa[x]]-1+cf[fa[x]]) up[x]+=(son[fa[x]]*dn[fa[x]]-dn[x]-c+up[fa[x]]*cf[fa[x]])/(son[fa[x]]-1+cf[fa[x]]);
    28     For(i,x) if ((k=to[i])!=fa[x]) fa[k]=x,Up(k,val[i]);
    29 }
    30 
    31 void dfs(int x){
    32     dfn[x]=++tim;
    33     For(i,x) if ((k=to[i])!=fa[x]){
    34         if (!dfn[k]) fa[k]=x,pre[k]=val[i],dfs(k);
    35         else if (dfn[k]>dfn[x]){
    36             for (int t=k; t!=x; t=fa[t]) a[++tot]=t,d[t]=1,cf[t]=2,b[tot]=pre[t];
    37             a[++tot]=x; d[x]=1; cf[x]=2; b[tot]=val[i];
    38         }
    39     }
    40 }
    41 
    42 int main(){
    43     freopen("bzoj2878.in","r",stdin);
    44     freopen("bzoj2878.out","w",stdout);
    45     scanf("%d%d",&n,&m);
    46     rep(i,1,m) scanf("%d%d%d",&u,&v,&w),add(u,v,w),add(v,u,w);
    47     rep(i,1,n) cf[i]=1;
    48     if (m==n-1){
    49         Dn(1,0); cf[1]=0;
    50         For(i,1) fa[k=to[i]]=1,Up(k,val[i]);
    51     }else{
    52         dfs(1);
    53         rep(i,1,tot) Dn(a[i],0);
    54         rep(i,1,tot){
    55             int x=a[i]; double k=0.5;
    56             for (int j=i%tot+1; j!=i; j=j%tot+1){
    57                 if (j%tot+1!=i) up[x]+=k*(b[F(j)]+dn[a[j]]*son[a[j]]/(son[a[j]]+1));
    58                             else up[x]+=k*(b[F(j)]+dn[a[j]]);
    59                 k/=son[a[j]]+1;
    60             }
    61             k=0.5;
    62             for (int j=F(i); j!=i; j=F(j)){
    63                 if (F(j)!=i) up[x]+=k*(b[j]+dn[a[j]]*son[a[j]]/(son[a[j]]+1));
    64                             else up[x]+=k*(b[j]+dn[a[j]]);
    65                 k/=son[a[j]]+1;
    66             }
    67         }
    68         rep(j,1,tot){
    69             int x=a[j];
    70             For(i,x) if (!d[k=to[i]]) fa[k]=x,Up(k,val[i]);
    71         }
    72     }
    73     rep(i,1,n) ans+=(up[i]*cf[i]+dn[i]*son[i])/(cf[i]+son[i]);
    74     printf("%.5lf
    ",ans/n);
    75     return 0;
    76 }
  • 相关阅读:
    Chrome 控制台console的用法[转]
    Page Visibility(页面可见性) API介绍、微拓展[转]
    移动端rem单位用法[转]
    JavaScript继承方式详解[转]
    说说React
    Flex 布局教程:语法篇[转]
    git 常用命令总结
    Supervisor 在ubuntu系统下添加自启动
    Django 通过APNS推送消息
    通过 python-xmp-toolkit 读取图片xmlp信息
  • 原文地址:https://www.cnblogs.com/HocRiser/p/9936830.html
Copyright © 2011-2022 走看看