考虑树的部分分怎么做。令f[i]为i向子树内走的期望路径长度,转移比较显然。算答案时先把其父亲的答案弄好就可以统计自己的答案了。

  环套树也类似。树里直接dp,对环上点暴力考虑环上的每条路径,算完后再在树里统计答案。

  说起来不是很难。事实上想清楚了也确实不是很难。

  不明白为什么不管啥题我都能把代码写的贼长。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 100010
int n,m,p[N],degree[N],nxtlen[N],t=-;
int dfn[N],low[N],top=,cnt=,tot=,circle[N];
bool flag[N<<],iscircle[N<<];
double f[N],g[N],ans=;
struct data{int to,nxt,len;
}edge[N<<];
void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;}
void dfs(int k,int from)
{
for (int i=p[k];~i;i=edge[i].nxt)
if (edge[i].to!=from&&!iscircle[edge[i].to])
{
dfs(edge[i].to,k);
degree[k]++;
f[k]+=f[edge[i].to]+edge[i].len;
}
if (degree[k]) f[k]/=degree[k];
}
void getans(int k,int from)
{
for (int i=p[k];~i;i=edge[i].nxt)
if (edge[i].to!=from)
{
g[edge[i].to]=(f[edge[i].to]*degree[edge[i].to]+edge[i].len+(g[k]*(degree[k]+(k>))-f[edge[i].to]-edge[i].len)/(degree[k]-(k==)))/(degree[edge[i].to]+);
getans(edge[i].to,k);
}
}
void getans2(int k,int from)
{
for (int i=p[k];~i;i=edge[i].nxt)
if (edge[i].to!=from&&!iscircle[edge[i].to])
{
g[edge[i].to]=(f[edge[i].to]*degree[edge[i].to]+edge[i].len+(g[k]*(degree[k]++(k==from))-f[edge[i].to]-edge[i].len)/(degree[k]+(k==from)))/(degree[edge[i].to]+);
getans2(edge[i].to,k);
}
}
void tarjan(int k,int from)
{
dfn[k]=low[k]=++cnt;
for (int i=p[k];~i;i=edge[i].nxt)
if (edge[i].to!=from)
{
if (!dfn[edge[i].to]) tarjan(edge[i].to,k),low[k]=min(low[k],low[edge[i].to]);
else low[k]=min(low[k],dfn[edge[i].to]);
if (low[edge[i].to]>dfn[k]) flag[i]=flag[i^]=;
}
}
void findcircle(int k)
{
circle[++tot]=k;iscircle[k]=;
for (int i=p[k];~i;i=edge[i].nxt)
if (!iscircle[edge[i].to]&&!flag[i]) findcircle(edge[i].to);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj2878.in","r",stdin);
freopen("bzoj2878.out","w",stdout);
#endif
n=read(),m=read();
memset(p,,sizeof(p));
for (int i=;i<=m;i++)
{
int x=read(),y=read(),z=read();
addedge(x,y,z),addedge(y,x,z);
}
if (m==n-)
{
dfs(,);
g[]=f[];
if (degree[]>) getans(,);
else g[edge[p[]].to]=(f[edge[p[]].to]*degree[edge[p[]].to]+edge[p[]].len)/(degree[edge[p[]].to]+),getans(edge[p[]].to,);
for (int i=;i<=n;i++) ans+=g[i];
}
else
{
for (int i=;i<=n;i++) if (!dfn[i]) tarjan(i,i);
for (int i=;i<=n;i++)
{
for (int j=p[i];~j;j=edge[j].nxt)
if (!flag[j]) {findcircle(i);break;}
if (tot) break;
}
for (int i=;i<=tot;i++)
for (int j=p[circle[i]];~j;j=edge[j].nxt)
if (edge[j].to==circle[i%tot+]) nxtlen[i]=edge[j].len;
for (int i=;i<=tot;i++) dfs(circle[i],circle[i]);
for (int i=;i<=tot;i++)
{
double P=;
int x=i%tot+,sum=nxtlen[i];
while (x!=i)
{
if (degree[circle[x]])
{
g[circle[i]]+=P*degree[circle[x]]/(degree[circle[x]]+(x%tot+!=i))*(f[circle[x]]+sum);
P/=(degree[circle[x]]+);
}
else if (x%tot+==i) g[circle[i]]+=P*sum;
sum+=nxtlen[x];
x=x%tot+;
}
}
for (int i=;i<=tot;i++)
{
double P=;
int x=i>?i-:tot,sum=nxtlen[x];
while (x!=i)
{
if (degree[circle[x]])
{
g[circle[i]]+=P*degree[circle[x]]/(degree[circle[x]]+((x>?x-:tot)!=i))*(f[circle[x]]+sum);
P/=(degree[circle[x]]+);
}
else if ((x>?x-:tot)==i) g[circle[i]]+=P*sum;
x=x>?x-:tot;
sum+=nxtlen[x];
}
g[circle[i]]+=f[circle[i]]*degree[circle[i]];
g[circle[i]]/=degree[circle[i]]+;
getans2(circle[i],circle[i]);
}
for (int i=;i<=n;i++) ans+=g[i];
}
printf("%.5lf",ans/n);
return ;
}

BZOJ2878 NOI2012迷失游乐园(树形dp+环套树+概率期望)的更多相关文章

  1. bzoj2878 [Noi2012]迷失游乐园 [树形dp]

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

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

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

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

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

  4. 【BZOJ-1040】骑士 树形DP + 环套树 + DFS

    1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3312  Solved: 1269[Submit][Status ...

  5. [BZOJ2878][NOI2012]迷失游乐园(环套树DP+概率)

    推荐讲解:https://www.cnblogs.com/Tunix/p/4561493.html 首先考虑树的情况,就是经典的树上概率DP.先DP出down表示从这个点向儿子走能走的期望长度,再DP ...

  6. BZOJ 1040 树形DP+环套树

    就是有n个点n条边,那么有且只有一个环那么用Dfs把在环上的两个点找到.然后拆开,从这条个点分别作树形Dp即可. #include <cstdio> #include <cstrin ...

  7. BZOJ2878 [Noi2012]迷失游乐园 【基环树 + 树形dp + 期望dp】

    题目链接 BZOJ2878 题解 除了实现起来比较长,思维难度还是挺小的 观察数据范围发现环长不超过\(20\),而我们去掉环上任何一个点就可以形成森林 于是乎我们枚举断掉的点,然后只需求出剩余每个点 ...

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

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

  9. bzoj2878 [Noi2012]迷失游乐园——概率期望DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2878 这个博客写得很好:https://www.cnblogs.com/qt666/p/72 ...

随机推荐

  1. python 另一种打开文章的方式——codecs

    通常我们使用python打开文件都是 open(‘beijing.txt’)或者是 with open(‘beijing.txt’)as f 那么今天来给你带来一个新的文档打开方式 python的co ...

  2. 【轮子狂魔】WeChatAPI 开源系统架构详解

    如果使用WeChatAPI,它扮演着什么样的角色? 从图中我们可以看到主要分为3个部分: 1.业务系统 2.WeChatAPI: WeChatWebAPI,主要是接收微信服务器请求: WeChatAP ...

  3. Linux学习之常用系统工作命令(一)

     由于centos和RHEL互通,两个版本可以相互学习,所以截图有两个界面 Linux系统与win系列是两个几乎完全不同的操作系统,但是就应用范围来说,是win系统更胜一筹,然而,这反而也成为win系 ...

  4. css学习杂记

    1.css中的&语法 &是sass的语法,代表上一级选择器. 例如: .el-row { margin-bottom: 20px; &:last-child { margin- ...

  5. Jenkins服务器维护

    Jenkins服务器维护 以下是一些基本的活动,一些是对 Jenkins 服务器维护的最佳实践 URL选项 在 Jenkins 实例 URL 有以下命令将开展对Jenkins实例的相关动作. http ...

  6. OpenCV颜色转换和皮肤检测

    本笔记重点记录OpenCV中的颜色转换和利用色彩空间的特性进行皮肤检测 颜色转换 实现原理 之所以要引入色调/饱和度/亮度的色彩空间概念,是因为人们喜欢凭直觉分辨各种颜色,而它与这种方式吻合.实际上, ...

  7. python初学者随笔Week2

    一.集合 去重,把一个列表变成集合,自动去重 关系测试,测试两组数据的交集,并集,差集关系 集合是无序的 集合的操作: list_1 = [1,4,5,7,3,6,7,9] list_1 = set( ...

  8. Firefox浏览器【书签工具栏】里的网址链接无法删除的解决办法

    今天使用Firefox浏览器,发现有一些我从来都没有访问的网站出现在[书签工具栏], 也不知道是什么原因被添加进来的(可能是安装某个插件被插的),于是点删除,发现还删除不了,很是老火,研究了一番,把删 ...

  9. Javascript开发者 常用知识

    Javascript是一种日益增长的语言,特别是现在ECMAScript规范按照每年的发布时间表发布.伴随着这门语言的规模化和快速发展,掌握JS(不仅仅是jQuery)的重要性,变得更加重要. 这不是 ...

  10. 20162325 金立清 S2 W3 C13

    20162325 2017-2018-2 <程序设计与数据结构>第3周学习总结 教材学习内容概要 查找是在一组项内找到指定目标或是确定目标不存在的过程 高效的查找使得比较的次数最少 Com ...