题目: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. lua笔记之userdata

    1.一直使用框架里封装好的c库,想着自己一点一点的写些例子,学习下,以后需要c库,可以自己写了. 下边是一个简单的userdata的例子--数组操作. newarray.c #include &quo ...

  2. DevExpress 给TreeList添加右键菜单

    只有在右击节点时才会触发 private void treeList1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == Mou ...

  3. JAVA实现计算三角形等平面图形的夹角问题

    问题重现 现在一平面上有三点,分别是x(x1,x2),y(y1,y2),z(z1,z2),图形大致如下 现要求用java代码求出∠YxZ的度数. 问题分析及数学模型 1.要求两直线的夹角,就想到数学中 ...

  4. 给定字符串数组,用map的key保存数组中字符串元素,value保存字符串元素出现次数,最后统计个字符串元素出现次数

    import java.util.HashMap; public class map1 { public static void main(String[] args) { String[] arra ...

  5. bzoj 2190: [SDOI2008]仪仗队 线性欧拉函数

    2190: [SDOI2008]仪仗队 Time Limit: 10 Sec  Memory Limit: 259 MB[Submit][Status][Discuss] Description 作为 ...

  6. EditText实现输入限制和校验

    EditText实现输入限制和校验 一.方法 1)输入限制 1.通过android:digits限制只能输入小写abc android:digits="abc" 2.通过andro ...

  7. 深入理解Lambda

    概述 Lambda是一个表达式,也可以说它是一个匿名函数.然而在使用它或是阅读Lambda代码的时候,却显得并不那么容易.因为它匿名,因为它删减了一些必要的说明信息(比如方法名).下面就来说说Lamb ...

  8. 四 web爬虫,scrapy模块标签选择器下载图片,以及正则匹配标签

    标签选择器对象 HtmlXPathSelector()创建标签选择器对象,参数接收response回调的html对象需要导入模块:from scrapy.selector import HtmlXPa ...

  9. c语言中的string

    1. strlen(char const* s); 函数传入的是c风格字符串(即以‘\0’结尾的字符数组),返回的长度为size_t(即unsigned int),其长度不包括'\0'. 2. str ...

  10. XML的两种解析方式

    JDK提供的XML解析方式分为两种:DOM方式和SAX方式DOM:Document Object Model.需要读取整个XML文档,先需要在内存中构架代表整个DOM树的Document对象,可以进行 ...