【NOI2012】迷失游乐园
题目链接:迷失游乐园(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】迷失游乐园的更多相关文章
- BZOJ 2878: [Noi2012]迷失游乐园( 树形dp )
一棵树的话直接树形dp(求出往下走和往上走的期望长度). 假如是环套树, 环上的每棵树自己做一遍树形dp, 然后暴力枚举(环上的点<=20)环上每个点跑经过环上的路径就OK了. -------- ...
- 【BZOJ 2878】 2878: [Noi2012]迷失游乐园 (环套树、树形概率DP)
2878: [Noi2012]迷失游乐园 Description 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩.进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m ...
- [bzoj2878][Noi2012]迷失游乐园(基环树dp)
[bzoj2878][Noi2012]迷失游乐园(基环树dp) bzoj luogu 题意:一颗数或是基环树,随机从某个点开始一直走,不走已经到过的点,求无路可走时的路径长期望. 对于一棵树: 用两个 ...
- NOI2012 : 迷失游乐园
终于补完NOI2012了好开心~ 题目大意:给定一棵树或者环套外向树,求出从中随机选一条简单路径的期望长度,环上点数不超过20. 设 d[x]表示x的度数,ch[x]表示x孩子个数 up[x]表示x向 ...
- 2878: [Noi2012]迷失游乐园 - BZOJ
Description 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩.进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环( ...
- 【BZOJ 2878】 [Noi2012]迷失游乐园
Description 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩.进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环( ...
- BZOJ2878 [Noi2012]迷失游乐园
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- bzoj2878 [Noi2012]迷失游乐园 [树形dp]
Description 放假了,小Z认为呆在家里特别无聊.于是决定一个人去游乐园玩. 进入游乐园后.小Z看了看游乐园的地图,发现能够将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环 ...
- [luogu2081 NOI2012] 迷失游乐园 (树形期望dp 基环树)
传送门 题目描述 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩. 进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环(即m ...
- bzoj 2878: [Noi2012]迷失游乐园
#include<iostream> #include<cstring> #include<cstdio> #define M 100005 #define ld ...
随机推荐
- 复制一个带random指针的链表
一个单链表,其中除了next指针外,还有一个random指针,指向链表中的任意某个元素.如何复制这样一个链表呢? 通过next来复制一条链是很容易的,问题的难点在于如何恰当地设置新链表中的random ...
- git设置只允许特定类型的文件
git设置只允许特定类型的文件 # 忽略所有文件 * # 不忽略目录 !*/ # 不忽略文件.gitignore和*.foo !.gitignore !*.foo
- Strom 消息处理机制 中英对照翻译 (Storm如何保证消息被完全处理)
官方链接: http://storm.incubator.apache.org/documentation/Guaranteeing-message-processing.html What does ...
- Android程序-计算器
基于Android 2.3.3做的一个练手计算器. 可解析带括号的四则运算. 解析算术表达式的时候,准备调用Webkit通过Js来解析的. 但是2.3.3存在Bug,Js调用Java会导致程序崩溃, ...
- BZOJ 1601 [Usaco2008 Oct]灌水:最小生成树
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1601 题意: Farmer John已经决定把水灌到他的n(1<=n<=300 ...
- 分享知识-快乐自己:MySQL中的约束,添加约束,删除约束,以及一些其他修饰
创建数据库: CREATE DATABASES 数据库名: 选择数据库: USE 数据库名: 删除数据库: DROP DATAVBASE 数据库名: 创建表: CREATE TABLE IF NOT ...
- ACM学习历程—HDU 5326 Work(树形递推)
Problem Description It’s an interesting experience to move from ICPC to work, end my college life an ...
- vue之axios+php+mysql
博主原创,未经许可请勿转载 哦 1.axios配置请看上篇 2.mysql数据库编写,表名为area_list 3.json.php文件在notebeans中编写 <?php header('C ...
- scaleform中ActionScript和UnrealScript的交互
转自:http://www.cnblogs.com/NEOCSL/p/4174134.html scaleform是制作UI的好工具: 1.他可以解放程序员用代码控制的UI效果,例如平移,旋转和缩放都 ...
- JavaScript总结(1)
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...