http://www.lydsy.com/JudgeOnline/problem.php?id=2878

题意:n个点的图,保证图联通,有n-1或者n条边,求从任意一个点出发,不经过相同点,最终无路可走的路径长度期望。

思路:m=n-1时,可以用dp,处理出i点往下,i点往上走的路径长度期望,然后O(n)统计就可以了。

m=n时,由于环上点点数不超过20,那这就是基环树,我们考虑枚举基环树上面的点i,假设我们到了i,并走向了i的子树。

这样我们就把环断开了,然后我们再两遍顺逆走这个环,就可以处理出up数组了,然后再分别下传到每个子树里。

 #include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
int flag,n,m,f[],len[],vis[],tot,go[],next[],cnt,cir[],huan[],first[],val[],du[];
double down[],up[];
int read(){
char ch=getchar();int t=,f=;
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
void insert(int x,int y,int z){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
val[tot]=z;
}
void add(int x,int y,int z){
insert(x,y,z);insert(y,x,z);
}
void dfs1(int x,int fa){
vis[x]=;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (vis[pur]) continue;
dfs1(pur,x);
down[x]+=(double)val[i]+(((double)down[pur])/((double)(du[pur]-+(du[pur]==))));
}
}
void dfs2(int x,int fa){
if (!cir[x]&&fa!=) up[x]=len[x]+((double)((double)up[fa]+down[fa]-len[x]-((double)down[x])/((double)du[x]-+(du[x]==))))/((double)(du[fa]-+(du[fa]==)));
vis[x]=;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (vis[pur]) continue;
f[pur]=x;
len[pur]=val[i];
dfs2(pur,x);
}
}
void work1(){
dfs1(,);
for (int i=;i<=n;i++) vis[i]=;
dfs2(,);
double ans=;
for (int i=;i<=n;i++) ans+=((double)down[i]+(double)up[i])/((double)du[i]);
ans/=((double)(n));
printf("%.5f\n",ans);
}
void dfs(int x,int fa){
vis[x]=;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (flag) return;
if (f[x]!=pur&&vis[pur]){
len[pur]=val[i];
int j=x;
while (j!=f[pur]){
cnt++;
cir[j]=;
huan[cnt]=j;
j=f[j];
}
flag=;
return;
}else if (!vis[pur]){
len[pur]=val[i];
f[pur]=x;
dfs(pur,x);
}
}
}
void work2(){
flag=;
dfs(,);cnt++;
for (int i=;i<=n;i++) vis[i]=;
for (int i=;i<cnt;i++) vis[huan[i]]=;
for (int i=;i<cnt;i++) dfs1(huan[i],);
for (int i=;i<cnt;i++){
int x=(i+)%cnt;double s=;
while (x!=i){
if ((x+)%cnt==i) up[huan[i]]+=(double)s*len[huan[(x-+cnt)%cnt]]+((double)(s*down[huan[x]]))/((double)(du[huan[x]]-+(du[huan[x]]==)));
else up[huan[i]]+=(double)s*len[huan[(x-+cnt)%cnt]]+((double)(s*down[huan[x]]))/((double)(du[huan[x]]-));
s=s/((double)(du[huan[x]]-));
x=(x+)%cnt;
}
x=(i-+cnt)%cnt;s=;
while (x!=i){
if ((x-+cnt)%cnt==i) up[huan[i]]+=(double)s*len[huan[x]]+((double)(s*down[huan[x]]))/((double)(du[huan[x]]-+(du[huan[x]]==)));
else up[huan[i]]+=(double)s*len[huan[(x)%cnt]]+((double)(s*down[huan[x]]))/((double)(du[huan[x]]-));
s=s/((double)(du[huan[x]]-));
x=(x-+cnt)%cnt;
}
}
for (int i=;i<=n;i++) vis[i]=;
for (int i=;i<cnt;i++) vis[huan[i]]=;
for (int i=;i<cnt;i++) dfs2(huan[i],);
double ans=;
for (int i=;i<=n;i++) ans+=(down[i]+up[i])/(du[i]);
printf("%.5f\n",ans/n);
}
int main(){
cnt=-;
n=read();m=read();flag=;
for (int i=;i<=m;i++){
int x=read(),y=read(),z=read();
add(x,y,z);
du[x]++;du[y]++;
}
if (m==n-) work1();
else work2();
}

BZOJ 2878 迷失游乐园的更多相关文章

  1. 【NOI2012】迷失游乐园

    题目链接:迷失游乐园(BZOJ)  迷失游乐园(Luogu) 独立完成的题,写一发题解纪念一波~ 模拟完样例大概可以知道是道树形DP了. 观察数据范围,发现是基环树,至少会有一个环. 先从树的部分开始 ...

  2. 【BZOJ】【2878】【NOI2012】迷失游乐园

    树形+基环树DP/数学期望 然而我并不会做…… 题解戳这里:http://blog.csdn.net/u011265346/article/details/46328543 好吧先考虑一个简单点的,当 ...

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

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

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

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

  5. BZOJ 2878 【NOI2012】 迷失游乐园

    题目链接:迷失游乐园 这道题也没有传说中的那么难写吗→_→ 似乎有篇博客讲得特详细……附上链接:戳这里 如果这道题不是基环树,而就是一棵树的话,我们来考虑改怎么做.因为树上的路径只有向上.向下两种走法 ...

  6. 【BZOJ2878】【NOI2012】迷失游乐园(动态规划)

    [BZOJ2878][NOI2012]迷失游乐园(动态规划) 题面 BZOJ 题解 记得以前考试的时候做过这道题目 这题的暴力还是非常显然的,每次\(dfs\)一下就好了. 时间复杂度\(O(n^2) ...

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

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

  8. 「NOI2012」迷失游乐园

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

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

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

随机推荐

  1. BIT_COUNT()和BIT_OR()

    在学习MySQL手册时,看到根据天数计算访问量时,出现了BIT_COUNT()和BIT_OR()两个函数来处理天数计算的问题 所使用的表格信息如下: mysql> select year,mon ...

  2. Android 操作手机内置存储卡中的文件

    场景:需要读取指定文件的内容,此文件是手动存储到手机内置存储卡中的,且手机上不存在SD卡. 对于android通过activity提供的openFileOutput和openFileInput可以直接 ...

  3. JVM virtual memory

    This has been a long-standing complaint with Java, but it's largely meaningless, and usually based o ...

  4. A51汇编器的解释

    A51汇编器是运行于IBM PC系列及其兼容机上的交叉汇编软件,其主要功能是将MCS-51系列单片机汇编语言源程序翻译成符合Intel目标文件格式的可再定位的目标代码,经过L51连接器的连接和装配,产 ...

  5. SqlServer计算周岁的函数

    CREATE Function Dbo.GetAge ( @birthday datetime, @now datetime ) Returns int As Begin Declare @Age i ...

  6. codility上的问题 (21) Upsilon 2012

    这是我目前最喜欢的codiltiy上的问题之一.问题描述是:给定一个整数数组A,所有的数均不相同.假设下标从0开始,找到一个数组B, 满足A[B[0]] > A[B[1]] > A[B[2 ...

  7. 【转】Device Tree(二):基本概念

    原文网址:http://www.wowotech.net/linux_kenrel/dt_basic_concept.html 一.前言 一些背景知识(例如:为何要引入Device Tree,这个机制 ...

  8. poj 1503 大数相加(java)

    代码: import java.math.*; import java.util.Scanner; public class Main { public static void main(String ...

  9. systemd-journald详解

    配置文件详解 [Journal] #Storage=persistent Storage=persistent #Compress=yes #Seal=yes #SplitMode=uid #Sync ...

  10. CharacterController 角色控制器实现移动和跳跃

    之前我使用SimpleMove来控制角色的移动, 后来又想实现人物的跳跃, 看见圣典里面是使用Move来实现的. =.= 然后我都把他们改成move来实现了 代码实现: using UnityEngi ...