BZOJ2878 NOI2012迷失游乐园(树形dp+环套树+概率期望)
考虑树的部分分怎么做。令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+环套树+概率期望)的更多相关文章
- bzoj2878 [Noi2012]迷失游乐园 [树形dp]
Description 放假了,小Z认为呆在家里特别无聊.于是决定一个人去游乐园玩. 进入游乐园后.小Z看了看游乐园的地图,发现能够将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环 ...
- BZOJ 2878: [Noi2012]迷失游乐园( 树形dp )
一棵树的话直接树形dp(求出往下走和往上走的期望长度). 假如是环套树, 环上的每棵树自己做一遍树形dp, 然后暴力枚举(环上的点<=20)环上每个点跑经过环上的路径就OK了. -------- ...
- [bzoj2878][Noi2012]迷失游乐园(基环树dp)
[bzoj2878][Noi2012]迷失游乐园(基环树dp) bzoj luogu 题意:一颗数或是基环树,随机从某个点开始一直走,不走已经到过的点,求无路可走时的路径长期望. 对于一棵树: 用两个 ...
- 【BZOJ-1040】骑士 树形DP + 环套树 + DFS
1040: [ZJOI2008]骑士 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3312 Solved: 1269[Submit][Status ...
- [BZOJ2878][NOI2012]迷失游乐园(环套树DP+概率)
推荐讲解:https://www.cnblogs.com/Tunix/p/4561493.html 首先考虑树的情况,就是经典的树上概率DP.先DP出down表示从这个点向儿子走能走的期望长度,再DP ...
- BZOJ 1040 树形DP+环套树
就是有n个点n条边,那么有且只有一个环那么用Dfs把在环上的两个点找到.然后拆开,从这条个点分别作树形Dp即可. #include <cstdio> #include <cstrin ...
- BZOJ2878 [Noi2012]迷失游乐园 【基环树 + 树形dp + 期望dp】
题目链接 BZOJ2878 题解 除了实现起来比较长,思维难度还是挺小的 观察数据范围发现环长不超过\(20\),而我们去掉环上任何一个点就可以形成森林 于是乎我们枚举断掉的点,然后只需求出剩余每个点 ...
- [luogu2081 NOI2012] 迷失游乐园 (树形期望dp 基环树)
传送门 题目描述 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩. 进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环(即m ...
- bzoj2878 [Noi2012]迷失游乐园——概率期望DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2878 这个博客写得很好:https://www.cnblogs.com/qt666/p/72 ...
随机推荐
- ASP.NET Core Token认证
翻译:Token Authentication in ASP.NET Core 令牌认证(Token Authentication)已经成为单页应用(SPA)和移动应用事实上的标准.即使是传统的B/S ...
- jmeter汉化
测试需要许多工具辅助工作,我们在使用这些工具之前需要对工具有一定的了解,第一步就是需要安装特定的软件. 因为工具基本上都是英文版的,所以菜鸟使用就面临汉化的问题,下面介绍几种汉化的办法: 一.万事不决 ...
- Xshell6远程访问linux及Xftp6远程针对linux系统中文件操作(附图文详解)
1.首先我们需要先做好前期准备工作,需要到XManager6官网上将Xshell及Xftp下载并安装,安装过程一直下一步就好了.这里是其官网:http://www.xshellcn.com/.安装完成 ...
- redis-4.0.2
redis-4.0.2.tar.gz 链接:https://pan.baidu.com/s/1qj4bSgM1s2InLikugRNqKA 提取码:tozq 复制这段内容后打开百度网盘手机App,操作 ...
- TP里where的查询方式,比如or应该怎么写?
这应该是个基础..只是我没有系统的学TP,所以用到了临时查了手册. 正常来说,thinkphp里的查询方式是: ThinkPHP可以支持直接使用字符串作为查询条件,但是大多数情况推荐使用数组或者对象来 ...
- jsp标签在JavaScript中使用时,可能会出现的一个问题。
直接上代码 <script type="text/javascript"> var E = window.wangEditor; var editor = new E( ...
- RHEL7 利用双网卡绑定实现VLAN
使用nmcli创建bond配置 #nmcli connection add type bond ifname bond0 con-name bond0 mode active-backup #nmcl ...
- ResNet——Deep Residual Learning for Image Recognition
1. 摘要 更深的神经网络通常更难训练,作者提出了一个残差学习的框架,使得比过去深许多的的网络训连起来也很容易. 在 ImageNet 数据集上,作者设计的网络达到了 152 层,是 VGG-19 的 ...
- dvwa——命令注入&文件包含
命令注入 commond_injection 源码.分析.payload: low: <?php if( isset( $_POST[ 'Submit' ] ) ) { // Get input ...
- python中__name__属性的使用
python常用模块目录 1.打印出函数名字而非函数名对应的地址 )打印的是函数地址 def func(): print("我是%s函数"%func) func() ------- ...