题目链接:迷失游乐园(BZOJ)  迷失游乐园(Luogu)

独立完成的题,写一发题解纪念一波~


模拟完样例大概可以知道是道树形DP了。

观察数据范围,发现是基环树,至少会有一个环。

先从树的部分开始考虑,如果没有环,怎么DP呢?

先选取一个点为根,f[i]表示从i节点出发走到其子树的路径期望长度。

那么f[x]= sum(f[son]+w[i])/(rd[x]-1),w[i]为son到x的边长,rd[x]为x的度数,当然如果到了根节点,就不必要减1。

然后再换根一波,统计答案就可以了。换根时注意节点度数的处理就行。

这样就能轻松拿到50分的良心部分分。

如果是基环树呢?

习惯把基环树看成一个“细菌”,把环放正中间考虑。

每一个在环上的点都连接着一个子树,先用前面树形DP的方法对每部分子树进行求解,先不换根。

对于环上每个点,可以逆时针走,也可以顺时针走,所以枚举它左右两条边断掉,拆成链。

在链上推一遍就可以得到从这个点往右或往左走的路径期望长。(环上点数量很少,复杂度在允许的范围内)

用这两种期望长度再去更新这个点,然后跑到这个点对应的子树去换根、统计答案。

算期望除以点度数时比较繁琐,写的时候要小心。

代码~

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm> #define For(i,a,b) for(register int i=a;i<=b;++i)
#define Dwn(i,a,b) for(register int i=a;i>=b;--i)
#define Re register
#define Db double using namespace std; const int N=1e5+; int head[N],nxt[N*],v[N*],cnt=;
Db f[N],w[N*],rd[N],z,ans=,Dn;
int n,x,y,m;
bool Fcr[N],vis[N],Ffd=; inline void read(int &v){
v=;
char c=getchar();
while(c<''||c>'')c=getchar();
while(c>=''&&c<='')v=v*+c-'',c=getchar();
}
inline void read(Db &v){
v=;
char c=getchar();
while(c<''||c>'')c=getchar();
while(c>=''&&c<='')v=v*+c-'',c=getchar();
}
void add(int ux,int vx,Db wx){
cnt++; rd[ux]+=;
nxt[cnt]=head[ux]; head[ux]=cnt; v[cnt]=vx; w[cnt]=wx;
cnt++; rd[vx]+=;
nxt[cnt]=head[vx]; head[vx]=cnt; v[cnt]=ux; w[cnt]=wx;
}
void dfsDP(int x,int fa){
for(Re int i=head[x];i;i=nxt[i]){
int vv=v[i]; if(vv==fa)continue;
if(Fcr[vv])continue;
dfsDP(vv,x);
f[x]+=f[vv]+w[i];
}
if(rd[x]>&&fa)f[x]/=(rd[x]-1.0);
if(fa==&&rd[x])f[x]/=rd[x];
}
void dfsFA(int x,int fa){
ans+=f[x]/Dn;
for(Re int i=head[x];i;i=nxt[i]){
int vv=v[i]; if(vv==fa)continue;
if(Fcr[vv])continue;
Db Bfx=f[x]; Db Bfv=f[vv]; Bfx=f[x]*rd[x]-f[vv]-w[i];
if(rd[x]>)Bfx/=(rd[x]-); f[vv]=f[vv]*(rd[vv]-)+Bfx+w[i];
f[vv]/=rd[vv];
dfsFA(vv,x);
f[vv]=Bfv;
}
}
int st[N],top=,tot=-,cr[N][];
Db dsf[N],dcr[N][],fx[N][];
void dfsCIR(int x,int fa){
vis[x]=; st[++top]=x;
for(Re int i=head[x];i;i=nxt[i]){
int vv=v[i]; if(vv==fa)continue;
if(vis[vv]){
Ffd=;
while(st[top]!=vv){
int stx=st[top--];
cr[++tot][]=stx; dcr[tot][]=dsf[stx]; Fcr[stx]=;
}
cr[++tot][]=vv; dcr[tot][]=w[i]; Fcr[vv]=;
return;
}
dsf[vv]=w[i];
dfsCIR(vv,x);
if(Ffd)return;
}
top--;
}
void getF12(int pos,int now){
int p=pos+;
Db Fx=;
if(p>tot)p=;
Fx=f[cr[p][now]];
do{
Fx+=dcr[p][now];
p++; if(p>tot)p=;
if(p==pos)break;
int cx=cr[p][now];
Db Fcx=f[cx]*(rd[cx]-);
Fx=(Fx+Fcx)/(rd[cx]-);
}while(p!=pos);
fx[ cr[pos][now] ][now]=Fx;
} int main(){
read(n); read(m); Dn=n;
memset(Fcr,,sizeof(Fcr));
memset(vis,,sizeof(vis));
For(i,,m){
read(x); read(y); read(z);
add(x,y,z);
}
if(m<n){
dfsDP(,); dfsFA(,);
printf("%.05lf",ans);
return ;
}
dfsCIR(,);
For(i,,tot){
rd[cr[i][]]-=;
dfsDP(cr[i][],);
rd[cr[i][]]+=;
}
For(i,,tot){
cr[i][]=cr[tot-i][];
if(i!=tot)dcr[i][]=dcr[tot-i-][];
else dcr[i][]=dcr[tot][];
} For(i,,tot){
getF12(i,); getF12(i,);
}
For(i,,tot){
int cx=cr[i][];
f[cx]*=(rd[cx]-);
f[cx]+=fx[cx][]+fx[cx][];
f[cx]/=rd[cx];
dfsFA(cx,);
}
printf("%.05lf",ans);
return ;
}

【NOI2012】迷失游乐园的更多相关文章

  1. BZOJ 2878: [Noi2012]迷失游乐园( 树形dp )

    一棵树的话直接树形dp(求出往下走和往上走的期望长度). 假如是环套树, 环上的每棵树自己做一遍树形dp, 然后暴力枚举(环上的点<=20)环上每个点跑经过环上的路径就OK了. -------- ...

  2. 【BZOJ 2878】 2878: [Noi2012]迷失游乐园 (环套树、树形概率DP)

    2878: [Noi2012]迷失游乐园 Description 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩.进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m ...

  3. [bzoj2878][Noi2012]迷失游乐园(基环树dp)

    [bzoj2878][Noi2012]迷失游乐园(基环树dp) bzoj luogu 题意:一颗数或是基环树,随机从某个点开始一直走,不走已经到过的点,求无路可走时的路径长期望. 对于一棵树: 用两个 ...

  4. NOI2012 : 迷失游乐园

    终于补完NOI2012了好开心~ 题目大意:给定一棵树或者环套外向树,求出从中随机选一条简单路径的期望长度,环上点数不超过20. 设 d[x]表示x的度数,ch[x]表示x孩子个数 up[x]表示x向 ...

  5. 2878: [Noi2012]迷失游乐园 - BZOJ

    Description 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩.进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环( ...

  6. 【BZOJ 2878】 [Noi2012]迷失游乐园

    Description 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩.进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环( ...

  7. BZOJ2878 [Noi2012]迷失游乐园

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  8. bzoj2878 [Noi2012]迷失游乐园 [树形dp]

    Description 放假了,小Z认为呆在家里特别无聊.于是决定一个人去游乐园玩. 进入游乐园后.小Z看了看游乐园的地图,发现能够将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环 ...

  9. [luogu2081 NOI2012] 迷失游乐园 (树形期望dp 基环树)

    传送门 题目描述 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩. 进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环(即m ...

  10. bzoj 2878: [Noi2012]迷失游乐园

    #include<iostream> #include<cstring> #include<cstdio> #define M 100005 #define ld ...

随机推荐

  1. 20145239 《Java程序设计》第6周学习总结

    20145239 <Java程序设计>第6周学习总结 教材学习内容总结 10.1.1串流设计 Java将输入/输出抽象化为串流,数据有来源及目的地,衔接两者的是串流对象. 输入串流代表对象 ...

  2. 【css学习整理】浮动,清除

    css内边距属性: padding padding-top right bottom left 如果是两个数字,指的是上下,左右 padding: 10px 20px  上下10  左右20 如果是三 ...

  3. Spring Boot2.0之全局捕获异常

    全局捕获异常,很明显的错误404返回给客户,很不好呀.整个web请求项目全局捕获异常,比如空指针直接返回给客户啊,那多操蛋呀~ 看这几个常用的注解: @ExceptionHandler 表示拦截异常 ...

  4. 1 准备学习redis

    首先,当然是搜索相关资料了 1 Redis 设计与实现 http://redisbook.com/ 2 Redis快速入门 http://www.yiibai.com/redis/redis_quic ...

  5. TYOI 1015 Game:博弈 结论【步数之和的奇偶性】

    题意: 明明和亮亮在玩一个游戏. 桌面上一行有n个格子,一些格子中放着棋子. 明明和亮亮轮流选择如下方式中的一种移动棋子(图示中o表示棋子,*表示空着的格子): (1)当一枚棋子的右边是空格子的话,可 ...

  6. DBA日记:一次reboot导致的严重失误

    昨天下午,一现场要添加RAC节点,db1节点正常运行,添加db2节点:在db2上做了安装的一些配置后,需要reboot, 于是直接就reboot:糟糕,这条命令错误地执行在db1上了,导致现场数据库直 ...

  7. ES搜索排序,文档相关度评分介绍——Field-length norm

    Field-length norm How long is the field? The shorter the field, the higher the weight. If a term app ...

  8. hadoop集群的安装

    Hadoop集群安装 1.配置JDK环境和设置主机名,本地解析 JDK环境教程: http://www.cnblogs.com/wangweiwen/p/6104189.html 本地解析: vim ...

  9. 物化视图基础概念、mview跨库迁移表

    概念:物化视图是一种特殊的物理表,“物化”(Materialized)视图是相对普通视图而言的.普通视图是虚拟表,应用的局限性大,任何对视图的查询,Oracle都实际上转换为视图SQL语句的查询.这样 ...

  10. sublime插件insertDate显示ISO时间

    1 下载insertDate插件以及安装完毕 2 把光标放在想插入ISO时间的地方 3 按住:alt+f5,之后,在sublime下面的Date format string输入:iso.之后按ente ...