题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2878

很好的树上概率题的思路,就是分成up和down。

代码中有众多小细节。让我弃疗好几天的致命小细节是dfs1里面那个sum要定义成double的!……

#include<iostream>
#include<cstdio>
#include<cstring>
#define db double
using namespace std;
const int N=1e5+;
int n,m,head[N],xnt,f[N],son[N],stack[N],top;
db down[N],up[N];
bool vis[N],in[N],flag;
struct Edge{
int next,to,w;
Edge(int n=,int t=,int w=):next(n),to(t),w(w) {}
}edge[N<<];
void add(int x,int y,int z)
{
edge[++xnt]=Edge(head[x],y,z);head[x]=xnt;
edge[++xnt]=Edge(head[y],x,z);head[y]=xnt;
}
void dfs1(int cr,int fa)
{
double sum=;//double
for(int i=head[cr],v;i;i=edge[i].next)
if((v=edge[i].to)!=fa&&!in[v])
{
son[cr]++;dfs1(v,cr);
sum+=down[v]+edge[i].w;//+edge[i].w!!
}
if(son[cr])down[cr]=sum/son[cr];
}
void dfs2(int cr,int fa,int d)
{
if(fa)//判断if(fa)!!
{
f[cr]=;//环上的点fa是0
up[cr]=d; //////如果放在下面的式子里,就少加了d ——但是怎么会有!(son[fa]-1+f[fa])的情况呢? //fa只有一条边的时候!
if(son[fa]-+f[fa])up[cr]+=(down[fa]*son[fa]-d-down[cr]+up[fa]*f[fa])/(son[fa]-+f[fa]);
// printf("cr=%d up=%.5lf(upfa=%.5lf)\n",cr,up[cr],up[fa]);
} //环上的点不求up,已在solve2里求过
for(int i=head[cr],v;i;i=edge[i].next)
if((v=edge[i].to)!=fa&&!in[v])dfs2(v,cr,edge[i].w);
}
void tarjan(int cr,int fa)
{
stack[++top]=cr;vis[cr]=;
for(int i=head[cr],v;i;i=edge[i].next)
if((v=edge[i].to)!=fa)
{
if(vis[v])
{
while(stack[top]!=v)in[stack[top--]]=;//!=v不是!=cr
in[stack[top--]]=;flag=;return;
}
else tarjan(v,cr);
if(flag)return;
}
top--;/////////
}
void solve(int root,int cr,int fa,double g,int d)/////自己的写法,判cr!=root!!
{
for(int i=head[cr],v;i;i=edge[i].next)
if(in[v=edge[i].to]&&v!=fa)
{
if(v==root)
{
up[root]+=g*(down[cr]+d);//
// printf("root=%d cr=%d up=%.5lf(down[cr]=%.5lf g=%.5lf)\n",root,cr,up[root],down[cr],g);
return;
}
if(cr!=root)up[root]+=g*(down[cr]+d)*son[cr]/(son[cr]+);//先+d再乘son[cr]
// printf("root=%d cr=%d up=%.5lf(down[cr]=%.5lf son[cr]=%d g=%.5lf)\n",root,cr,up[root],down[cr],son[cr],g);
if(cr==root)solve(root,v,cr,g/,d+edge[i].w); //son可能有多个
else solve(root,v,cr,g/(son[cr]+),d+edge[i].w);
}
}
int main()
{
scanf("%d%d",&n,&m);int x,y,z;
if(n==)
{
printf("0.00000");return ;
}
for(int i=;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);add(x,y,z);
}
if(m==n-)dfs1(,),dfs2(,,);
else{
tarjan(,);
for(int i=;i<=n;i++)if(in[i])dfs1(i,);
for(int i=;i<=n;i++)if(in[i])solve(i,i,,,);///!!!!!!!!
for(int i=;i<=n;i++)if(in[i])f[i]=,dfs2(i,,);
}
// for(int i=1;i<=n;i++)printf("i=%d up=%.5lf down=%.5lf\n",i,up[i],down[i]);
double sum=;
for(int i=;i<=n;i++)sum+=(down[i]*son[i]+up[i]*f[i])/(son[i]+f[i]);
printf("%.5lf",sum/n);
return ;
}

bzoj 2878 [Noi2012]迷失游乐园——树上的期望dp的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. 【BZOJ】4872: [Shoi2017]分手是祝愿 期望DP

    [题意]给定n盏灯的01状态,操作第 i 盏灯会将所有编号为 i 的约数的灯取反.每次随机操作一盏灯直至当前状态能够在k步内全灭为止(然后直接灭),求期望步数.n,k<=10^5. [算法]期望 ...

  9. bzoj 1415: [Noi2005]聪聪和可可 期望dp+记忆化搜索

    期望dp水题~ 你发现每一次肯定是贪心走 2 步,(只走一步的话就可能出现环) 然后令 $f[i][j]$ 表示聪在 $i$,可在 $j$,且聪先手两个人碰上面的期望最小次数. 用记忆化搜索转移就行了 ...

随机推荐

  1. AtCoder Regular Contest 095

    AtCoder Regular Contest 095 C - Many Medians 题意: 给出n个数,求出去掉第i个数之后所有数的中位数,保证n是偶数. \(n\le 200000\) 分析: ...

  2. java-四则运算二

    1.实验目的:是否有乘除法,括号,多项式运算. 2.思路:利用简单的循环switch语句进行循环输出随机数 3.程序源代码: package jiajianchengchu; import java. ...

  3. UnsupportedOperationException

    java不支持该功能,多见于, Arrays.asList() ,然后使用remove和add方法.     因为asarraylist的集合是一个转化来的集合,它的大小是固定的.不能进行长度修改. ...

  4. 控制语句1:真假与if 语句

    一.真假与运算符 1.1 真假的划分.查看 任何数据都可以分为两类:True 与 False False : 0,None,空的数据结构例如:[] ,{},str1 = '' True  :除了上面情 ...

  5. Hibernate 悲观锁,乐观锁

    业务逻辑的实现过程中,往往需要保证数据访问的排他性.因此,我们就需要通过一些机制来保证这些数据在某个操作过程中不会被外界修改,这样的机制,在这里,也就是所谓的“锁”,即给我们选定的目标数据上锁,使其无 ...

  6. css11动态效果

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  7. Struts02---实现struts2的三种方式

    01.创建普通类 /** * 01.普通类 * 写一个execute() 返回String类型值 * */ public class HelloAction01 { public String exe ...

  8. Audio/Movie/Image

    Audio 1. 引入AVFoundation 库,此库用于处理音频的播放. > 使用AVAudioPlayer 播放音频,此类只能播放本地音频文件.对于流媒体(边下边播)的播放使用第三方框架实 ...

  9. 照相、从相册上取照片、播放音频、播放本地视频、播放网络视频、MPMoviePlayerController

    一.照相.从相册上去照片 1. 先判断是否支持照相功能 *判断当前设备是否支持照相功能,支持返回YES 否则返回NO 注意:模拟器不支持照相功能 把握一个原则只要是物理硬件相关的功能模拟器都不支持 例 ...

  10. 理解字符串 Boyer-Moore 算法

    作者: 阮一峰 上一篇介绍了 kmp算法 但是,它并不是效率最高的算法,实际采用并不多. 各种文本编辑器的"查找"功能(Ctrl+F),大多采用Boyer-Moore算法. Boy ...