[bzoj2878][Noi2012]迷失游乐园(基环树dp)
Posted rikurika
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[bzoj2878][Noi2012]迷失游乐园(基环树dp)相关的知识,希望对你有一定的参考价值。
题意:一颗数或是基环树,随机从某个点开始一直走,不走已经到过的点,求无路可走时的路径长期望。
对于一棵树:
用两个$dp$数组分别记录从这个点起向上向下走的期望
向下走的$dp$不用多说
向上走的$dp$:
对于从$u$计算$v$的dp
$dp[v]$应当是从u向周围引出所有路径减去走向t的路径的期望后再除以$deg_u-1$
对于基环树:
环上的点很少。
此时环上的点的向上$dp$指从u出发向环上两头走的期望。
如何计算:对于环上每一个点都向环的两头各dp一次取平均值。
完毕。
#include<cstdio> #include<algorithm> using namespace std; const int N=100011; const double eps=1e-8; template<typename TP>void read(TP &kk) #define ak * TP phy=0,ioi=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘)if(ch==‘-‘)ioi=-1;ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘)phy=phy*10+ch-‘0‘;ch=getchar(); kk=phy ak ioi; int n,m; struct sumireko int to,ne,w; e[N*2]; int he[N],ecnt; void addline(int f,int t,int w) e[++ecnt].to=t; e[ecnt].ne=he[f]; he[f]=ecnt; e[ecnt].w=w; bool onr[N]; double deg[N],sc[N],dpu[N],dpd[N]; void dfs1(int x,int f) for(int i=he[x],t;i;i=e[i].ne) t=e[i].to; if(t==f||onr[t]) continue; dfs1(t,x); dpd[x]+=dpd[t]+e[i].w; if(sc[x]>eps) dpd[x]/=sc[x]; void dfs2(int x,int f) for(int i=he[x],t;i;i=e[i].ne) t=e[i].to; if(f==t||onr[t]) continue; dpu[t]=e[i].w; if(deg[x]-1.0>eps)dpu[t]+=(dpd[x]*sc[x]-e[i].w-dpd[t]+dpu[x]*(deg[x]-sc[x]))/(deg[x]-1.0); dfs2(t,x); int rnd[N],hp; int sp;bool vv[N]; int find(int x,int f) if(vv[x])sp=x;return 1; vv[x]=1;int tmp; for(int i=he[x],t;i;i=e[i].ne) t=e[i].to; if(t==f) continue; if(tmp=find(t,x)) if(tmp==1) rnd[++hp]=x; onr[x]=1; if(x!=sp) return 1; return 2; return 0; double dpt[N]; void dfs3(int x,int f,int o,int s) if(!o) int g=0; for(int i=he[x],t;i;i=e[i].ne) t=e[i].to; if(!onr[t]) continue; g++;dfs3(t,x,g,s); dpu[x]+=dpt[t]+e[i].w; dpu[x]/=2; return; double tmp=0; dpt[x]=0; for(int i=he[x],t;i;i=e[i].ne) t=e[i].to; if(!onr[t]||t==s||t==f) continue; dfs3(t,x,o,s); dpt[x]+=dpt[t]+e[i].w; tmp+=1; if(sc[x]+tmp>eps) dpt[x]=(dpt[x]+dpd[x]*sc[x])/(sc[x]+tmp); double ans; int xi,yi,wi; int main() read(n),read(m); for(int i=1;i<=m;i++) read(xi),read(yi),read(wi); addline(xi,yi,wi),addline(yi,xi,wi),deg[xi]+=1,deg[yi]+=1; if(m==n-1) for(int i=1;i<=n;i++) sc[i]=deg[i]-1; sc[1]+=1; dfs1(1,0); dfs2(1,0); for(int i=1;i<=n;i++) ans+=(dpd[i]*sc[i]+dpu[i])/deg[i]; ans/=n; printf("%.5lf\n",ans); return 0; find(1,0); for(int i=1;i<=n;i++) sc[i]=deg[i]-(onr[i]?2.0:1.0); for(int i=1;i<=hp;i++) dfs1(rnd[i],0); for(int i=1;i<=hp;i++) dfs3(rnd[i],0,0,rnd[i]); for(int i=1;i<=hp;i++) dfs2(rnd[i],0); for(int i=1;i<=n;i++) ans+=(dpd[i]*sc[i]+dpu[i]*(deg[i]-sc[i]))/deg[i]; ans/=n; printf("%.5lf\n",ans); return 0;
以上是关于[bzoj2878][Noi2012]迷失游乐园(基环树dp)的主要内容,如果未能解决你的问题,请参考以下文章
bzoj2878 [Noi2012]迷失游乐园 [树形dp]