树形+基环树DP/数学期望


  然而我并不会做……

  题解戳这里:http://blog.csdn.net/u011265346/article/details/46328543

  好吧先考虑一个简单点的,当m=n-1时,整个是一个树形的结构,无根树我们一般还是转成有根树来处理……然后既然是无法回头的,那么我们可以定一下方向:向下或者向上(废话)

  定义一下:

  son[x]为x的儿子的数量

  down[x]表示从x这个点出发,向叶子们走的期望长度。

  怎么算呢?其实就是所有可能的情况(所有的儿子)加起来,再求个平均,所以我们有$$down[x]=\frac{\sum (down[y]+len(x->y))}{son[x]}$$

  up[x]表示从x这个点出发,经过父亲,走到某个叶子的期望长度。

  这个看上去好难算啊……怎么算呢?我们先算出来每个结点的down[x],然后从上往下DP,这里我们需要考虑的是x的父亲 f ,我们从x向上走到他父亲 f 后(len(x->f)),可以向 f 其他的儿子走,这种方案的期望长度之和为$$ son[f]*down[f]-down[x]-len(f->x) $$如果是继续向上,这种方案的期望长度为$up[f]$,所以有$$up[x]=len(x->f) + \frac{ son[f]*down[f]-down[x]-len(f->x) + up[f]}{son[f]-1+1}$$这里son[f]-1表示是向其他儿子走,+1表示的是继续向上,这么多种方案的概率是相等的。

  那么答案怎么算?当然是$$ans=\sum_{i=1}^n \frac{down[i]*son[i]+up[i]}{son[i]+1} $$

  好的到这里我们就解决了树上的问题,那么环套树其实就是需要特殊处理一下 环上的结点以及与环直接相连的结点,怎么做呢?

  肯定是要先找环的啦= =那么我们dfs搞搞找出环上所有结点,题目限制这样的结点不多,就20个= =

  有一个东西是跟树的情况一样的,那就是从环上某个结点直接向与它相连的外向树上走的期望长度,也就是所有的down[cir[i]],这里cir[i]表示环上的点。

  算出down[cir[i]]以后,跟据刚刚的经验,我们就可以用down来算up啦!同样是从上往下算up的值,只不过这里的“树根”变成了一个环,环上的点的up值其实就是沿着环走到其他的任意一个环上的点,然后再向下走的期望长度啦,举个例子吧:(其实这一段看代码比较好……)

  环上的点编号为1、2、3、4、5,那么对于1来说,顺时针走的话,走到2的概率为1,走到3的概率为$\frac{1}{son[2]+1}$,走到4的话就再乘$\frac{1}{son[3]+1}$……逆时针走的话同理。

  同时我们沿着环每走到一个位置就加上从这里向外向树走的期望长度(注意绕一圈走到头的地方与之前的不一样,因为出发点不可能经过两次)。

  表达式比较难写……好吧其实是我懒,而且长得并不好看,还是看代码比较好:

 F(i,,tot){
int x=cir[i];
double k=;
for(int j=nex[x];j!=x;j=nex[j]){
if (nex[j]!=x)
up[x]+=k*(len[hash[pre[j]]][hash[j]]+down[j]*son[j]/(son[j]+));
else
up[x]+=k*(len[hash[pre[j]]][hash[j]]+down[j]);
k/=(son[j]+);
}
k=;
for(int j=pre[x];j!=x;j=pre[j]){
if (pre[j]!=x)
up[x]+=k*(len[hash[nex[j]]][hash[j]]+down[j]*son[j]/(son[j]+));
else
up[x]+=k*(len[hash[nex[j]]][hash[j]]+down[j]);
k/=(son[j]+);
}
up[x]/=;
}

  算出所有环上的点的up[i]以后,外向树的up[i]就跟树上情况一样了……不过由于环上的点的父节点相当于是有两个,所以这里重新定义一个fa[i],表示 i 的父亲结点的数量。那么有$$up[x]=len(x->f) + \frac{ son[f]*down[f]-down[x]-len(f->x) + up[f]*fa[f] }{son[f]-1+fa[f]}$$

另外,对于上面的所有公式,要小心分母可能为0的情况。

 /**************************************************************
Problem: 2878
User: Tunix
Language: C++
Result: Accepted
Time:556 ms
Memory:9876 kb
****************************************************************/ //BZOJ 2878
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
inline int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=1e5+,INF=~0u>>;
typedef long long LL;
/******************tamplate*********************/
int to[N<<],nxt[N<<],head[N],cnt;
double l[N<<];
void ins(int x,int y,double z){
to[++cnt]=y; nxt[cnt]=head[x]; head[x]=cnt; l[cnt]=z;
} int n,m; int vis[N],flag;
double son[N],fa[N],up[N],down[N];
int cir[N],tot,hash[N];
int pre[N],nex[N];
double len[][]; void Findcir(int x,int f){
vis[x]=;
for(int i=head[x];i;i=nxt[i])
if (to[i]!=f){
if (vis[to[i]]){
flag=to[i];
return;
}
Findcir(to[i],x);
if (flag>){
if (flag==x) flag=-;
return;
}
if (flag==-) break;
}
vis[x]=;
}
void dfs_cir(int x,int f){
if (hash[x]) return;
cir[++tot]=x;
hash[x]=tot;
fa[x]=;
for(int i=head[x];i;i=nxt[i]){
if (to[i]==f) continue;
if (!vis[to[i]]) continue; pre[to[i]]=x;
nex[x]=to[i];
dfs_cir(to[i],x);
len[hash[x]][hash[to[i]]]=len[hash[to[i]]][hash[x]]=l[i];
break;
}
} void dfsdown(int x,int f){
for(int i=head[x];i;i=nxt[i])
if (!vis[to[i]] && to[i]!=f){
fa[to[i]]=;
dfsdown(to[i],x);
son[x]++;
down[x]+=down[to[i]]+l[i];
}
if (son[x]) down[x]/=son[x];
} void dfsup(int x,int f,double ee){
up[x]=ee;
if (fa[f]+son[f]>)
up[x]+=(fa[f]*up[f]+son[f]*down[f]-down[x]-ee)/(fa[f]+son[f]-);
for(int i=head[x];i;i=nxt[i])
if (to[i]!=f) dfsup(to[i],x,l[i]);
} int main(){
#ifndef ONLINE_JUDGE
freopen("2878.in","r",stdin);
freopen("2878.out","w",stdout);
#endif
n=getint(); m=getint();
F(i,,m){
int x=getint(),y=getint(),z=getint();
ins(x,y,z); ins(y,x,z);
}
Findcir(,);
if (m<n){
dfsdown(,);
for(int i=head[];i;i=nxt[i])
dfsup(to[i],,l[i]);
}else{
F(i,,n)
if (vis[i]){
dfs_cir(i,);
break;
}
F(i,,tot) dfsdown(cir[i],);
F(i,,tot){
int x=cir[i];
double k=;
for(int j=nex[x];j!=x;j=nex[j]){
if (nex[j]!=x)
up[x]+=k*(len[hash[pre[j]]][hash[j]]+down[j]*son[j]/(son[j]+));
else
up[x]+=k*(len[hash[pre[j]]][hash[j]]+down[j]);
k/=(son[j]+);
}
k=;
for(int j=pre[x];j!=x;j=pre[j]){
if (pre[j]!=x)
up[x]+=k*(len[hash[nex[j]]][hash[j]]+down[j]*son[j]/(son[j]+));
else
up[x]+=k*(len[hash[nex[j]]][hash[j]]+down[j]);
k/=(son[j]+); }
up[x]/=;
}
F(j,,tot){
for(int i=head[cir[j]];i;i=nxt[i])
if (!hash[to[i]]) dfsup(to[i],cir[j],l[i]);
}
}
double ans=;
F(i,,n) ans+=(up[i]*fa[i]+down[i]*son[i])/(fa[i]+son[i]);
printf("%.5lf\n",ans/n);
return ;
}

2878: [Noi2012]迷失游乐园

Time Limit: 10 Sec  Memory Limit: 512 MBSec  Special Judge
Submit: 503  Solved: 321
[Submit][Status][Discuss]

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

HINT

Source

[Submit][Status][Discuss]

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

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

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

  2. bzoj 2878 [Noi2012]迷失游乐园——树上的期望dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2878 很好的树上概率题的思路,就是分成up和down. 代码中有众多小细节.让我弃疗好几天的 ...

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

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

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

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

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

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

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

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

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

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

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

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

  9. 【BZOJ 2878】 [Noi2012]迷失游乐园

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

  10. NOI2012 : 迷失游乐园

    终于补完NOI2012了好开心~ 题目大意:给定一棵树或者环套外向树,求出从中随机选一条简单路径的期望长度,环上点数不超过20. 设 d[x]表示x的度数,ch[x]表示x孩子个数 up[x]表示x向 ...

随机推荐

  1. 黑马程序员_java基础笔记(08)...GUI,网络编程,正则表达式

    —————————— ASP.Net+Android+IOS开发..Net培训.期待与您交流! —————————— GUI(Graphical User Interface)(图形用户接口):用图形 ...

  2. 码云Android项目构建注意事项(转载)

    1.ant项目 build.xml必须位于项目根目录. 2.maven项目 pom.xml必须位于项目根目录. 3.gradle项目 由于gradle的配置灵活,我们做了一些规范,并且增加了一下机制来 ...

  3. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

  4. Servlet的一点小结

    1.什么是servlet servlet是一个Java applet,一个帮助程序.用于帮助浏览器从服务器中获取资源.浏览器-servlet-服务器三者的关系如图所示. 2.servlet的生命周期 ...

  5. 启动win8.1时提示 api-ms-win-crt-runtime-l1-1-0.dll丢失

    电脑里没有安装windows的更新KB2999226 到微软官网 https://www.microsoft.com/zh-cn/download/details.aspx?id=49081 下载对应 ...

  6. Could not open JDBC Connection for transaction; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (Could not create connection to database server.

    报错信息:Could not open JDBC Connection for transaction; nested exception is org.apache.commons.dbcp.SQL ...

  7. 八皇后II

    用一个数组state记录已经选择的每一行皇后所在的位置,DFS count = 0 N = 8 state = [0]*N def dfs(row): global count for col in ...

  8. 深入理解yield

    yield的英文单词意思是生产,刚接触Python的时候感到非常困惑,一直没弄明白yield的用法. 只是粗略的知道yield可以用来为一个函数返回值塞数据,比如下面的例子: 1 2 3 def ad ...

  9. 【10.4校内测试】【轮廓线DP】【中国剩余定理】【Trie树+博弈】

    考场上几乎是一看就看出来轮廓线叻...可是调了两个小时打死也过不了手出样例!std发下来一对,特判对的啊,转移对的啊,$dp$数组竟然没有取max!!! 某位考生当场死亡. 结果下午又请了诸位dala ...

  10. ng-show和ng-if的区别

    第一点区别是, ng-if 在后面表达式为 true 的时候才创建这个 dom 节点, ng-show 是初始时就创建了,用display:block 和 display:none 来控制显示和不显示 ...