Description

放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩。进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点、m条道路的无向连通图,且该图中至多有一个环(即m只可能等于n或者n-1)。小Z现在所在的大门也正好是一个景点。小Z不知道什么好玩,于是他决定,从当前位置出发,每次随机去一个和当前景点有道路相连的景点,并且同一个景点不去两次(包括起始景点)。贪玩的小Z会一直游玩,直到当前景点的相邻景点都已经访问过为止。小Z所有经过的景点按顺序构成一条非重复路径,他想知道这条路径的期望长度是多少?小Z把游乐园的抽象地图画下来带回了家,可是忘了标哪个点是大门,他只好假设每个景点都可能是大门(即每个景点作为起始点的概率是一样的)。同时,他每次在选择下一个景点时会等概率地随机选择一个还没去过的相邻景点。

Input

第一行是两个整数n和m,分别表示景点数和道路数。 接下来行,每行三个整数Xi, Yi, Wi,分别表示第i条路径的两个景点为Xi, Yi,路径长Wi。所有景点的编号从1至n,两个景点之间至多只有一条道路。

Output

共一行,包含一个实数,即路径的期望长度,保留五位小数

Sample Input

4 3
1 2 3
2 3 1
3 4 4

Sample Output

6.00000

【样例解释】样例数据中共有6条不同的路径: 路径 长度 概率
1-->4 8 1/4
2-->1 3 1/8
2-->4 5 1/8
3-->1 4 1/8
3-->4 4 1/8
4-->1 8 1/4
因此期望长度 = 8/4 + 3/8 + 5/8 + 4/8 + 4/8 + 8/4 = 6.00
【评分方法】本题没有部分分,你程序的输出只有和标准答案的差距不超过0.01时,才能获得该测试点的满分,否则不得分。
【数据规模和约定】对于100%的数据,1 <= Wi <= 100。 测试点编号 n m 备注
1 n=10 m = n-1 保证图是链状
2 n=100 只有节点1的度数大于2
3 n=1000 /
4 n=100000 /
5 n=100000 /
6 n=10 m = n /
7 n=100 环中节点个数<=5
8 n=1000 环中节点个数<=10
9 n=100000 环中节点个数<=15
10 n=100000 环中节点个数<=20

 
这是我迄今为止做过的最麻烦的一道树形DP,还是那句话,我的DP就是弱,你打我啊
对于树来说
利用F[i]表示每一个点到达它的子树的期望长度
利用D[i]=Σ(F[j]+e[i,j])(j为i的儿子)
利用du[i]表示一个点的度数
则可求得F[i]=D[i]/du[i]
如此进行一遍dfs即可求出以一个点为根的数值
此时我们再进行一遍dfs,求出以任一点为根的D数组
主要利用D[j]+=(D[i]-f[j]-e[i,j])/(du[i]-1)+e[i,j](j为i的儿子)
这样就可以解出所有的D值
至于M==N的情况,我们可以暴力处理环,毕竟环只有最大20
首先是判断去掉环的情况,那么图就变成了无根森林,和树的处理方式相同,进行一遍dfs
再是找出环,利用gg[i]数组表示从i点出发的期望长度,g数组表示从i点出发单向走的长度
gg[i]=g[j]+g[k]+e[i,j]+e[j,k](i,k为i左右相连的边)
暴力求解出环上的所有gg
最后环上点d[i]+=gg[i],du[i]+=2;
 #include<cstdio>
#define ld long double
#include<cstring>
#include<iostream>
using namespace std;
const int N=;
struct ee{int to,next,w;}e[N*];
int n,m,u,v,w,cnt,root,timer;
int head[N],du[N],vis[N],fa[N];
ld f[N],gg[N],g[N],d[N];
bool c[N];
void ins(int u,int v,int w){
e[++cnt].to=v;e[cnt].next=head[u];e[cnt].w=w;head[u]=cnt;
e[++cnt].to=u;e[cnt].next=head[v];e[cnt].w=w;head[v]=cnt;
}
void dfs1(int x){
vis[x]=;
for (int i=head[x];i;i=e[i].next){
int v=e[i].to;
if (!vis[v]&&!c[v]){
du[x]++;
dfs1(v);
d[x]+=f[v]+e[i].w;
}
}
if (du[x]) f[x]=(d[x]+0.0)/du[x];
if(x!=root) du[x]++;
} void dfs2(int x){
vis[x]=;
for(int i=head[x];i;i=e[i].next){
int v=e[i].to;
if(!vis[v]&&!c[v]){
d[v]+=(d[x]-f[v]-e[i].w)/max(,(du[x]-))+e[i].w;
dfs2(v);
}
}
} void find(int x){
vis[x]=++timer;
for (int i=head[x];i;i=e[i].next){
int v=e[i].to;
if(!vis[v]) fa[v]=x,find(v);
else if(fa[x]!=v&&vis[v]<vis[x]){
c[v]=;
for(;x!=v;)
c[x]=,x=fa[x];
}
}
} void solve_cycle(int x,int fa){
bool flag=;
g[x]=;//1 wa
for (int i=head[x];i;i=e[i].next){
int v=e[i].to;
if(v!=root&&v!=fa&&c[v]){
flag=;
solve_cycle(v,x);
g[x]+=g[v]+e[i].w;
}
}
if(x==root) return;
int k=du[x];if(!k)k++;
if(flag)g[x]=(d[x]+0.0)/k;
else k=du[x]+,g[x]=(g[x]+d[x])/k;
} int main(){
scanf("%d%d",&n,&m);
for (int i=;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
ins(u,v,w);
}
if(m==n-){
root=;
dfs1();
memset(vis,,sizeof(vis));
dfs2();
}else{
find();
memset(vis,,sizeof(vis));
for (int i=;i<=n;i++) if(c[i]) {
root=i;
dfs1(i);
}
for (int i=;i<=n;i++) if(c[i]) {
root=i;
solve_cycle(i,);
gg[i]=g[i];
}
memset(vis,,sizeof(vis));
for(int i=;i<=n;i++) if(c[i]){
du[i]+=;
d[i]+=gg[i];
}
for(int i=;i<=n;i++) if(c[i]) dfs2(i);
}
double ans=;
for (int i=;i<=n;i++) ans+=(d[i]+0.0)/du[i];
printf("%.5lf\n",ans/n);
}

【BZOJ 2878】 [Noi2012]迷失游乐园的更多相关文章

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

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

  2. bzoj 2878 [Noi2012]迷失游乐园——树上的期望dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2878 很好的树上概率题的思路,就是分成up和down. 代码中有众多小细节.让我弃疗好几天的 ...

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

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

  4. bzoj 2878: [Noi2012]迷失游乐园【树上期望dp+基环树】

    参考:https://blog.csdn.net/shiyukun1998/article/details/44684947 先看对于树的情况 设d[u]为点u向儿子走的期望长度和,du[u]为u点的 ...

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

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

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

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

  7. BZOJ 2878([Noi2012]-失落的游乐园树DP+出站年轮加+后市展望DP+vector的erase)

    2878: [Noi2012]迷失乐园 Time Limit: 10 Sec  Memory Limit: 512 MBSec  Special Judge Submit: 319  Solved:  ...

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

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

  9. NOI2012 : 迷失游乐园

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

随机推荐

  1. Adobe Edge Animate –地球自转动画的实现,类似flash遮罩层的效果

    Adobe Edge Animate –地球自转动画的实现,类似flash遮罩层的效果 版权声明: 本文版权属于 北京联友天下科技发展有限公司. 转载的时候请注明版权和原文地址. 目前Edge的功能尚 ...

  2. 【几何模板加点小思路】hdu-4998 Rotate

    用几何模板敲的,也有直接公式推的,追求短代码的可以点右上角小红了...... 题意就是想想一个物体分别做绕某一点(给出坐标)旋转p度(给出角度)后,其位置等价于绕哪一点旋转多少度,输出该等价点及其等价 ...

  3. hdu 3938 Portal

    Portal Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Sub ...

  4. Linux 命令 - netstat: 检查网络设置及相关统计数据

    netstat 程序可以用于查看不同的网络设置及数据.通过使用其丰富的参数选项,我们可以查看网络启动过程的许多特性. 命令格式 netstat [options] 命令参数 -r, --route 显 ...

  5. iOS中的动画

    iOS中的动画 Core Animation Core Animation是一组非常强大的动画处理API,使用它能做出非常绚丽的动画效果,而且往往是事半功倍,使用它需要添加QuartzCore .fr ...

  6. self指向函数地址 动态调用函数的简单例子

    #import <Foundation/Foundation.h> @interface Person : NSObject - (void)test1; - (void)test2:(N ...

  7. [GeekBand] 面向对象的设计模式(C++)(2)

    本篇笔记紧接上篇,继续学习设计模式. 4. 对象创建类设计模式 通过对象创建模式绕开new,来避免对象创建(new)过程中所导致的紧耦合,从而支持对象创建的稳定.它是接口抽象之后的第一步工作. 4.1 ...

  8. SQLBindCol---数组输出

    SQLSetStmtAttr(hstmt,SQL_ATTR_ROW_BIND_TYPE,SQL_BIND_BY_COLUMN,0); SQLSetStmtAttr(hstmt,SQL_ATTR_ROW ...

  9. SEO视频教程集合在线观看

    seo是搜索引擎优化(Search Engine Optimization)的英文缩写,是指为了从搜索引擎中获得更多的免费流量,从网站结构.内容建设方案.用户互动传播.页面等角度进行合理规划,使网站更 ...

  10. wap手机端解决返回上一页,js

    <input id="hd_referrer" type="hidden" />                <a href="j ...