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.00000000

【例子解释】例子数据中共同拥有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

Solution

up[x]表示从节点x向上走的期望长度,down[x]表示从节点x向下走的期望长度。

假设是一棵树,两遍dfs搞定。

假设有一个环:

以环上每一个点为向下根dfs出down[x]。

但此时对于环上的点的down[x]不是向下走的期望长度,还要枚举环上的点,计算沿环走的期望长度。

最后计算非环上的点的up值。

话说12年的题有点丧病啊。

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 100005;

struct Edge{
int to;
double v;
Edge() {}
Edge(int a, double b) : to(a), v(b) {}
}; vector<Edge> edges[MAXN];
int n, m;
int vis[MAXN], flag;
double son[MAXN], fa[MAXN], up[MAXN], down[MAXN];
int cir[MAXN], tot, hash[MAXN];
int pre[MAXN], nex[MAXN];
double len[25][25]; void findCircle(int x, int f) {
vis[x] = 1;
for (int i = 0; i < edges[x].size(); i++) {
Edge e = edges[x][i];
if (e.to == f) continue;
if (vis[e.to]) {
flag = e.to;
return;
}
findCircle(e.to, x);
if (flag > 0) {
if (flag == x) flag = -1;
return;
}
if (flag == -1) break;
}
vis[x] = 0;
} void dfs_cir(int x, int f) {
if (hash[x]) return;
cir[++tot] = x;
hash[x] = tot;
fa[x] = 2;
for (int i = 0; i < edges[x].size(); i++) {
Edge e = edges[x][i];
if (e.to == f) continue;
if (!vis[e.to]) continue; pre[e.to] = x;
nex[x] = e.to;
dfs_cir(e.to, x);
len[hash[x]][hash[e.to]] = len[hash[e.to]][hash[x]] = e.v;
break;
}
} void dfsdown(int x, int f) {
for (int i = 0; i < edges[x].size(); i++) {
Edge e = edges[x][i];
if (!vis[e.to] && e.to != f) {
fa[e.to] = 1;
dfsdown(e.to, x);
son[x]++;
down[x] += down[e.to] + e.v;
}
}
if (son[x]) down[x] /= son[x];
} void dfsup(int x, int f, double ee) {
up[x] = ee;
if (fa[f] + son[f] > 1) up[x] += (fa[f] * up[f] + son[f] * down[f] - down[x] - ee) / (fa[f] + son[f] - 1);
for (int i = 0; i < edges[x].size(); i++)
if (edges[x][i].to != f) dfsup(edges[x][i].to, x, edges[x][i].v);
} int main() {
scanf("%d %d", &n, &m);
int a, b;
double c;
for (int i = 0; i < m; i++) {
scanf("%d %d %lf", &a, &b, &c);
edges[a].push_back(Edge(b, c));
edges[b].push_back(Edge(a, c));
}
findCircle(1, 0);
if (m < n) {
dfsdown(1, 0);
for (int i = 0; i < edges[1].size(); i++)
dfsup(edges[1][i].to, 1, edges[1][i].v);
} else {
for (int i = 1; i <= n; i++) {
if (vis[i]) {
dfs_cir(i, 0);
break;
}
}
for (int i = 1; i <= tot; i++)
dfsdown(cir[i], 0);
for (int i = 1; i <= tot; i++) {
int u = cir[i];
double k = 1;
for (int j = nex[u]; j != u; j = nex[j]) {
if (nex[j] != u) up[u] += k * (len[hash[pre[j]]][hash[j]] + down[j] * son[j] / (son[j] + 1));
else up[u] += k * (len[hash[pre[j]]][hash[j]] + down[j]);
k /= (son[j] + 1);
}
k = 1;
for (int j = pre[u]; j != u; j = pre[j]) {
double z = up[j];
if (pre[j] != u) up[u] += k * (len[hash[nex[j]]][hash[j]] + down[j] * son[j] / (son[j] + 1));
else up[u] += k * (len[hash[nex[j]]][hash[j]] + down[j]);
k /= (son[j] + 1);
}
up[u] /= 2;
}
for (int i = 1; i <= tot; i++) {
for (int j = 0; j < edges[cir[i]].size(); j++) {
Edge e = edges[cir[i]][j];
if (!hash[e.to]) dfsup(e.to, cir[i], e.v);
}
}
} double ans = 0;
for (int i = 1; i <= n; i++) {
ans += (up[i] * fa[i] + down[i] * son[i]) / (fa[i] + son[i]);
}
printf("%.5lf\n", ans / n);
return 0;
}

bzoj2878 [Noi2012]迷失游乐园 [树形dp]的更多相关文章

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

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

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

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

  3. BZOJ2878 NOI2012迷失游乐园(树形dp+环套树+概率期望)

    考虑树的部分分怎么做.令f[i]为i向子树内走的期望路径长度,转移比较显然.算答案时先把其父亲的答案弄好就可以统计自己的答案了. 环套树也类似.树里直接dp,对环上点暴力考虑环上的每条路径,算完后再在 ...

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

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

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

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

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

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

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

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

  8. BZOJ2878 [Noi2012]迷失游乐园

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

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

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

随机推荐

  1. BZOJ 3831 单调队列DP

    思路: 这好像是我刚学单调性的时候做的题 (我是不会告诉你 我被这题教做人了的...) i-stk[head]>k 删队头 f[stk[tail]]>f[i]||(f[stk[tail]] ...

  2. SQLServer2008 关于CASE WHEN

    CASE WHEN的两种格式 1.简单Case函数 CASE sex WHEN '1' THEN '男' WHEN '2' THEN '女' ELSE '其他' END 2.Case搜索函数 CASE ...

  3. swift-delegate(代理)或者block传值

    1:delegate或者block传值 import UIKit class ViewController: UIViewController,TestDelegatePassValueDelegat ...

  4. ie8及其以下版本兼容性问题之input file隐藏上传文件

    文件上传时,默认的file标签很难看,而且每个浏览器下都有很大差距.因此我们基本都把真正的file标签给隐藏,然后创建一个标签来替代它.但是由于IE出于安全方面的考虑上传文件时必须点击file的浏览按 ...

  5. 推荐系统入门:作为Rank系统的推荐系统(协同过滤)

    知乎:如何学习推荐系统? 知乎:协同过滤和基于内容的推荐有什么区别? 案例:推荐系统实战?  数据准备:实现推荐栏位:重构接口:后续优化. 简书:实现实时推荐系统的三种方式?基于聚类和协同过滤:基于S ...

  6. fatal error C1083: 无法打开包括文件:“stdio.h

    现象: vs2012一直fatal error C1083: 无法打开包括文件:"stdio.h" 不知道配置太多,动到了什么地方,出现了这个问题: 在: 解决方案--调试源文件 ...

  7. python自动发邮件库yagmail(转)

    一般发邮件方法 我以前在通过Python实现自动化邮件功能的时候是这样的: import smtplib from email.mime.text import MIMEText from email ...

  8. element-ui按需引入

    { "name": "vue-test2", "description": "A Vue.js project", &q ...

  9. XML的解析方式

    //解析和输出XML public void showXml() { string filepath = Application.dataPath + @"/my.xml"; if ...

  10. vue 中获取到数据点击失效

    // var data = Object.assign([],ret.t); //动态创建dom后点击 元素不添加背景色 Object.assign(复制下)