原题传送门

这是当时冬令营课上讲的题,咕咕咕到了现在

如果这题没有环套树的话,就很套路了

需要两个数组up[i]和down[i],down[i]表示从i点第一步向下走的期望距离,up[i]表示从i点第一步向上走的期望距离,先求down,然后求up

\(down[i]=\frac{\sum_{j|son[i]}(down[j]+len(i,j))}{son[i]}\)

\(up[i]=\frac{up[fa[i]]+down[fa[i]]*son[fa[i]]-down[i]-len(fa[i],i)}{son[fa[i]]}+len(fa[i],i)\)

环套树就比较麻烦了qwqwq,但题目上告诉了我们一个环的特性:环长不超过20

那么方法也就很明了了,先将环上每个节点的子树的down处理出来,再枚举每个点,计算从这个点开始顺着环走的期望(因为不能回头,所以就是正反各搜一遍)

最后再更新每颗子树的up

最终答案就是每个节点up与down的和除以度数之和除以点数

程序中珂以再加上滚动数组,否则up和down很容易整错qwqwq

#include <bits/stdc++.h>
#define N 100005
#define db double
#define getchar nc
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline db Max(register db a,register db b)
{
return a>b?a:b;
}
struct edge{
int to,next,w;
}e[N<<1];
int head[N],cnt=0;
inline void add(register int u,register int v,register int w)
{
e[++cnt]=(edge){v,head[u],w};
head[u]=cnt;
}
int n,m,rt,tim;
int vis[N],cir[N],du[N],fa[N];
db d[N],f[N],g[N],tp[N];
db ans;
inline void dfs1(register int x)
{
vis[x]=1;
for(register int i=head[x];i;i=e[i].next)
if(!vis[e[i].to]&&!cir[e[i].to])
{
dfs1(e[i].to);
++du[x];
d[x]+=f[e[i].to]+e[i].w;
}
if(du[x])
f[x]=d[x]/(db)du[x];
if(x!=rt)
++du[x];
}
inline void dfs2(register int x)
{
vis[x]=1;
for(register int i=head[x];i;i=e[i].next)
if(!vis[e[i].to]&&!cir[e[i].to])
{
d[e[i].to]+=(d[x]-f[e[i].to]-e[i].w)/Max(1,du[x]-1)+e[i].w;
dfs2(e[i].to);
}
}
inline void dfs3(register int x)
{
vis[x]=++tim;
for(register int i=head[x],j;i;i=e[i].next)
if(e[i].to!=fa[x])
{
if(!vis[e[i].to])
{
fa[e[i].to]=x;
dfs3(e[i].to);
}
else if(vis[e[i].to]<vis[x])
for(cir[e[i].to]=1,j=x;j!=e[i].to;j=fa[j])
cir[j]=1;
}
}
inline void dfs4(register int x,register int fa)
{
bool flag=0;
g[x]=0;
for(register int i=head[x];i;i=e[i].next)
if(e[i].to!=rt&&e[i].to!=fa&&cir[e[i].to])
{
flag=1;
dfs4(e[i].to,x);
g[x]+=g[e[i].to]+e[i].w;
}
if(x==rt)
return;
int k=du[x];
k?k:++k;
if(!flag)
g[x]=d[x]/(db)k;
else
k=du[x]+1,g[x]=(g[x]+d[x])/(db)k;
}
int main()
{
n=read(),m=read();
for(register int i=1;i<=m;++i)
{
int u=read(),v=read(),w=read();
add(u,v,w),add(v,u,w);
}
if(m==n-1)
{
rt=1;
dfs1(1);
memset(vis,0,sizeof(vis));
dfs2(1);
}
else
{
dfs3(1);
memset(vis,0,sizeof(vis));
for(register int i=1;i<=n;++i)
if(cir[i])
rt=i,dfs1(i);
for(register int i=1;i<=n;++i)
if(cir[i])
{
rt=i;
dfs4(i,0);
tp[i]=g[i];
}
memset(vis,0,sizeof(vis));
for(register int i=1;i<=n;++i)
if(cir[i])
du[i]+=2,d[i]+=tp[i];
for(register int i=1;i<=n;++i)
if(cir[i])
rt=i,dfs2(i);
}
for(register int i=1;i<=n;++i)
ans+=d[i]/(db)du[i];
printf("%.5lf",ans/(db)n);
return 0;
}

【题解】Luogu P2081 [NOI2012]迷失游乐园的更多相关文章

  1. Luogu P2081 [NOI2012]迷失游乐园 | 期望 DP 基环树

    题目链接 基环树套路题.(然而各种错误调了好久233) 当$m=n-1$时,原图是一棵树. 先以任意点为根做$dp$,求出从每一个点出发,然后只往自己子树里走时路径的期望长度. 接着再把整棵树再扫一遍 ...

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

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

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

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

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

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

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

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

  6. NOI2012 : 迷失游乐园

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

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

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

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

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

  9. 【bzoj2878】 Noi2012—迷失游乐园

    http://www.lydsy.com/JudgeOnline/problem.php?id=2878 (题目链接) 题意 求基环树上以任意点为起点的简单路径期望长度. Solution 啊啊啊好丑 ...

随机推荐

  1. ubuntu安装elasticsearch

    0x00安装jdk ElasticSearch需要安装jdk1.8以上版本的支持,所以需要先安装jdk.linux下如何安装可以查看另一篇博客 0x01 下载elasticsearch 在es官网下载 ...

  2. js 检查登录态方法封装(闭包、状态缓存)

    前端页面开发时,经常需要异步校验登录态,每次都重新copy之前写的方法,比较繁琐不好维护,固将登录态校验封装成一个js. (function(){ //登录状态 1 登录态有效 2 登录态无效 3 请 ...

  3. redis相关操作

    #连接主机 redis-cli -h 192.168.2.109 -p 6379 #通过密码登录 auth "yourpassword" #存取值 set hello world ...

  4. Jmeter简单的接口测试举例

    推荐文章:http://www.cnblogs.com/puresoul/p/5092628.html 1.创建线程组 本次测试模块为一个线程组(可以在线程组内列出模块内的需要测试的接口) 2.在线程 ...

  5. Nginx(二)-服务模式运行nginx之WINSW

    虽然使用命令行控制ngix很简单,但是如果作为一个服务工作的话能更方便地启动.停止或者设置依赖项. 这里使用开源项目Windows Service Wrapper 来实现. github下载地址:ht ...

  6. inux中ifreq 结构体分析和使用(转)

    标签: it 分类: socket 结构原型: struct ifreq{#define IFHWADDRLEN 6 union {  char ifrn_name[IFNAMSIZ];   } if ...

  7. 2019-04-20 Python之科学计算库学习总结

    一.numpy库和matplotlib库的学习 (1)numpy库介绍:科学计算包,支持N维数组运算.处理大型矩阵.成熟的广播函数库.矢量运算.线性代数.傅里叶变换.随机数生成,并可与C++/Fort ...

  8. CSAPP:第二章学习笔记:斗之气2段

    一.字长:虚拟地址通过一个字来编码,字长为32位,则可以标识2^32个地址空间,每个空间为一个字节,故为4G 二.字节序:当解释多个字节类型时,存在大小端字节序问题 0x1234567,在大小端表示法 ...

  9. python的高级数组之稀疏矩阵

    稀疏矩阵的定义: 具有少量非零项的矩阵(在矩阵中,若数值0的元素数目远多于非0元素的数目,并且非0元素分布没有规律时,)则称该矩阵为稀疏矩阵:相反,为稠密矩阵.非零元素的总数比上矩阵所有元素的总数为矩 ...

  10. CDI services--interceptors(拦截器)

    1.拦截器综述 拦截器的功能是定义在Java拦截器规范. 拦截器规范定义了三种拦截点: 业务方法拦截, 生命周期回调侦听, 超时拦截(EJB)方法. 在容器的生命周期中进行拦截 1 2 3 4 pub ...